summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorflorian <florian@3ad0048d-3df7-0310-abae-a5850022a9f2>2021-02-07 20:53:59 +0000
committerflorian <florian@3ad0048d-3df7-0310-abae-a5850022a9f2>2021-02-07 20:53:59 +0000
commit605e85d8ae30f0027f1fc8df0de5de18ab210c89 (patch)
tree2fc78a3ff7ccacfa26d6faf1b7c846ddb1bea79a
parent611ca8ad56d84d4c163bb8b38c43d683fec3e476 (diff)
downloadfpc-605e85d8ae30f0027f1fc8df0de5de18ab210c89.tar.gz
-- Zusammenführen von r48108 bis r48520 in ».«:
A tests/webtbs/uw38385b.pp A tests/webtbs/tw38351.pp A tests/webtbs/tw38316.pp U tests/Makefile A tests/webtbf/tw37217.pp A tests/webtbs/tw32139.pp A tests/webtbs/tw38429.pp A tests/webtbs/tw38413.pp A tests/webtbs/uw38385a.pp A tests/webtbs/tw38390.pp A tests/webtbs/tw38306.pp A tests/webtbs/tw38337.pp C tests/bench/bcase.pp U rtl/unix/sysutils.pp U rtl/unix/oscdeclh.inc U rtl/linux/x86_64/syscall.inc U rtl/linux/x86_64/si_prc.inc U rtl/linux/linux.pp U rtl/linux/m68k/cprt0.as U rtl/linux/m68k/dllprt0.as U rtl/linux/mips/cprt0.as U rtl/linux/mips/prt0.as U rtl/linux/i386/si_prc.inc U rtl/linux/si_impl.inc U rtl/linux/system.pp U rtl/i386/cpu.pp U rtl/objpas/sysconst.pp U rtl/objpas/sysutils/syshelpo.inc U rtl/amiga/powerpc/execf.inc U tests/test/units/sysutils/tfile1.pp A tests/test/units/sysutils/tfileage.pp A tests/test/units/linux/tfutimesen.pp U tests/test/units/linux/tstatx.pp A tests/test/units/linux/tutimensat.pp A tests/test/cg/tpara4.pp U tests/test/theapthread.pp A tests/webtbf/tw24434.pp A tests/webtbf/tw38287.pp A tests/webtbs/tw34027.pp A tests/webtbs/uw38429.pp A tests/webtbs/tw38412.pp A tests/webtbs/tw38385.pp A tests/webtbs/uw38385c.pp U tests/webtbs/tw37060.pp A tests/webtbs/tw38339.pp U tests/Makefile.fpc U tests/utils/testsuite/utests.pp U compiler/utils/mkx86inl.pp U compiler/utils/ppuutils/ppudump.pp U compiler/nmem.pas U compiler/msg/errorda.msg U compiler/msg/errorf.msg U compiler/msg/errorid.msg U compiler/msg/errorpli.msg U compiler/msg/errorru.msg U compiler/m68k/aoptcpu.pas U compiler/systems/t_darwin.pas U compiler/utils/msg2inc.pp U compiler/utils/Makefile.fpc U compiler/cfidwarf.pas U compiler/msg/errord.msg U compiler/msg/errores.msg U compiler/msg/errorheu.msg U compiler/msg/errorpl.msg U compiler/msg/errorr.msg U compiler/m68k/cgcpu.pas U compiler/rgobj.pas U compiler/Makefile.fpc U compiler/utils/Makefile U compiler/ngtcon.pas U compiler/msg/errorct.msg U compiler/msg/errore.msg U compiler/msg/errorhe.msg U compiler/msg/errorn.msg U compiler/msg/errorptu.msg C compiler/msgtxt.inc C compiler/msgidx.inc U compiler/systems/t_freertos.pas U compiler/Makefile U compiler/utils/mkz80ins.pp U compiler/aasmcnst.pas U compiler/ncon.pas U compiler/msg/errordu.msg U compiler/msg/errorfi.msg U compiler/msg/erroriu.msg U compiler/msg/errorpt.msg U compiler/msg/errorues.msg U compiler/ncgvmt.pas U compiler/systems/t_embed.pas U compiler/systems/t_bsd.pas U compiler/dbgcodeview.pas U compiler/x86/agx86nsm.pas U compiler/systems/t_win16.pas U compiler/verbose.pas U compiler/x86/aasmcpu.pas U compiler/x86/nx86mat.pas U compiler/systems/t_amiga.pas U compiler/x86/cgx86.pas U compiler/x86/nx86inl.pas U compiler/systems/t_win.pas U compiler/x86/cx86mminnr.inc U compiler/x86/aoptx86.pas U compiler/x86/nx86set.pas U compiler/systems.pas U compiler/avr/navradd.pas U compiler/avr/raavrgas.pas U compiler/aarch64/aasmcpu.pas U compiler/jvm/hlcgcpu.pas U compiler/jvm/njvmmat.pas U compiler/psabiehpi.pas U compiler/options.pas U compiler/avr/cpupara.pas U compiler/avr/navrmat.pas U compiler/aarch64/aoptcpu.pas U compiler/jvm/njvmmem.pas U compiler/jvm/njvminl.pas U compiler/pgenutil.pas U compiler/globtype.pas U compiler/avr/cgcpu.pas U compiler/avr/aoptcpu.pas U compiler/aarch64/agcpugas.pas U compiler/jvm/dbgjasm.pas U compiler/jvm/cpubase.pas U compiler/ogomf.pas U compiler/i8086/symcpu.pas U compiler/x86/rax86.pas U compiler/arm/aoptcpu.pas U compiler/avr/agavrgas.pas U compiler/avr/rgcpu.pas U compiler/aarch64/cgcpu.pas U compiler/jvm/agjasmin.pas U compiler/nflw.pas U compiler/i8086/n8086mem.pas U packages/graph/src/inc/graph.tex A packages/fcl-net/tests U compiler/i8086/n8086tcon.pas U compiler/ncginl.pas U compiler/symdef.pas U compiler/i8086/cpupara.pas U compiler/nbas.pas U compiler/scandir.pas U compiler/hlcgobj.pas U compiler/nadd.pas U compiler/psub.pas U compiler/armgen/aoptarm.pas U compiler/aggas.pas U compiler/optloop.pas U compiler/scanner.pas U compiler/x86_64/nx64mat.pas U compiler/ogbase.pas U compiler/i386/aoptcpu.pas U packages/fcl-passrc/src/pasresolver.pp U packages/pastojs/src/fppas2js.pp U packages/rtl-objpas/src/inc/dateutil.inc A packages/fcl-net/tests/netdbtest.pp U compiler/x86_64/aoptcpu.pas U compiler/ncal.pas U compiler/fpcdefs.inc U packages/pastojs/tests/tcmodules.pas U packages/rtl-objpas/src/inc/variants.pp U packages/fcl-net/src/netdb.pp A packages/pasjpeg/examples/demo.lpi U compiler/x86_64/cpupara.pas U compiler/dbgstabs.pas U compiler/aoptobj.pas U packages/fcl-passrc/tests/tcresolver.pas U packages/pastojs/src/pas2jspcucompiler.pp U packages/fcl-base/src/bufstream.pp U packages/fcl-stl/src/gdeque.pp U compiler/x86_64/cpuelf.pas U compiler/ncnv.pas U compiler/pdecsub.pas U packages/fcl-passrc/src/pparser.pp U packages/pastojs/src/pas2jsfiler.pp U packages/fcl-base/src/eventlog.pp A packages/fcl-net/tests/tresolvertests.pp U packages/pasjpeg/examples/example.pas U packages/fcl-registry/tests/Makefile U packages/fcl-registry/src/regini.inc U packages/fcl-db/src/sqldb/interbase/ibconnection.pp A packages/fcl-registry/tests/tregtestframework.pp U packages/fcl-registry/fpmake.pp U packages/fcl-registry/src/winreg.inc U packages/fcl-registry/tests/tregistry2.pp A packages/fcl-registry/tests/regtestbasics.pp U packages/fcl-registry/src/xmlreg.pp A packages/fcl-registry/tests/regtcxmlreg.pp U packages/fcl-registry/tests/Makefile.fpc D packages/fcl-registry/tests/regtestframework.pp D packages/fcl-registry/tests/testbasics.pp D packages/fcl-registry/tests/tcxmlreg.pp U packages/fcl-registry/src/registry.pp U packages/rtl-extra/fpmake.pp U utils/fpdoc/fpdoc.pp U utils/fpdoc/dw_html.pp U utils/fpdoc/mkfpdoc.pp U utils/fpdoc/dw_latex.pp U utils/fpdoc/dw_xml.pp U utils/fpdoc/fpmake.pp U packages/fpmkunit/src/fpmkunit.pp U utils/fpdoc/dw_chm.pp U utils/fpdoc/dw_basehtml.pp A utils/fpdoc/fpdocstrs.pp U utils/fpdoc/dw_dxml.pp U utils/fpdoc/dw_txt.pp U utils/fpdoc/fpdocxmlopts.pas U packages/fcl-db/src/sqldb/sqldb.pp U packages/fv/src/views.pas U utils/fpdoc/dwriter.pp U utils/fpdoc/fpdoc.lpi U utils/fpdoc/dw_basemd.pp U utils/fpdoc/dw_man.pp U utils/fpdoc/fpdocproj.pas U packages/fcl-db/src/sqldb/mysql/mysqlconn.inc U packages/rtl-extra/src/bsd/osdefs.inc U utils/fpdoc/dw_markdown.pp U utils/fpdoc/fpdocclasstree.pp U utils/fpdoc/dglobals.pp U utils/fpdoc/dw_linrtf.pp U utils/fpdoc/dwlinear.pp U utils/pas2js/dist/rtl.js U utils/fpdoc/fpclasschart.pp U utils/fpdoc/dw_ipflin.pas U utils/fpdoc/makeskel.pp -- Aufzeichnung der Informationen für Zusammenführung von r47033 bis r48520 in ».«: U . -- Aufzeichnung der Informationen für Zusammenführung von r47033 bis r48520 in »rtl«: U rtl Konfliktübersicht: Textkonflikte: 3 Konfliktübersicht: Textkonflikte: 3 git-svn-id: https://svn.freepascal.org/svn/fpc/branches/tg74@48521 3ad0048d-3df7-0310-abae-a5850022a9f2
-rw-r--r--avx512-0037785/compiler/Makefile22
-rw-r--r--avx512-0037785/compiler/Makefile.fpc23
-rw-r--r--avx512-0037785/compiler/aarch64/aasmcpu.pas20
-rw-r--r--avx512-0037785/compiler/aarch64/agcpugas.pas3
-rw-r--r--avx512-0037785/compiler/aarch64/aoptcpu.pas7
-rw-r--r--avx512-0037785/compiler/aarch64/cgcpu.pas3
-rw-r--r--avx512-0037785/compiler/aasmcnst.pas16
-rw-r--r--avx512-0037785/compiler/aggas.pas1
-rw-r--r--avx512-0037785/compiler/aoptobj.pas10
-rw-r--r--avx512-0037785/compiler/arm/aoptcpu.pas7
-rw-r--r--avx512-0037785/compiler/armgen/aoptarm.pas19
-rw-r--r--avx512-0037785/compiler/avr/agavrgas.pas2
-rw-r--r--avx512-0037785/compiler/avr/aoptcpu.pas1
-rw-r--r--avx512-0037785/compiler/avr/cgcpu.pas22
-rw-r--r--avx512-0037785/compiler/avr/cpupara.pas4
-rw-r--r--avx512-0037785/compiler/avr/navradd.pas3
-rw-r--r--avx512-0037785/compiler/avr/navrmat.pas2
-rw-r--r--avx512-0037785/compiler/avr/raavrgas.pas10
-rw-r--r--avx512-0037785/compiler/avr/rgcpu.pas10
-rw-r--r--avx512-0037785/compiler/cfidwarf.pas3
-rw-r--r--avx512-0037785/compiler/dbgcodeview.pas2
-rw-r--r--avx512-0037785/compiler/dbgstabs.pas2
-rw-r--r--avx512-0037785/compiler/fpcdefs.inc25
-rw-r--r--avx512-0037785/compiler/globtype.pas4
-rw-r--r--avx512-0037785/compiler/hlcgobj.pas19
-rw-r--r--avx512-0037785/compiler/i386/aoptcpu.pas2
-rw-r--r--avx512-0037785/compiler/i8086/cpupara.pas3
-rw-r--r--avx512-0037785/compiler/i8086/n8086mem.pas2
-rw-r--r--avx512-0037785/compiler/i8086/n8086tcon.pas1
-rw-r--r--avx512-0037785/compiler/i8086/symcpu.pas1
-rw-r--r--avx512-0037785/compiler/jvm/agjasmin.pas3
-rw-r--r--avx512-0037785/compiler/jvm/cpubase.pas4
-rw-r--r--avx512-0037785/compiler/jvm/dbgjasm.pas2
-rw-r--r--avx512-0037785/compiler/jvm/hlcgcpu.pas4
-rw-r--r--avx512-0037785/compiler/jvm/njvminl.pas3
-rw-r--r--avx512-0037785/compiler/jvm/njvmmat.pas1
-rw-r--r--avx512-0037785/compiler/jvm/njvmmem.pas3
-rw-r--r--avx512-0037785/compiler/m68k/aoptcpu.pas44
-rw-r--r--avx512-0037785/compiler/m68k/cgcpu.pas38
-rw-r--r--avx512-0037785/compiler/msg/errorct.msg4
-rw-r--r--avx512-0037785/compiler/msg/errord.msg6
-rw-r--r--avx512-0037785/compiler/msg/errorda.msg4
-rw-r--r--avx512-0037785/compiler/msg/errordu.msg6
-rw-r--r--avx512-0037785/compiler/msg/errore.msg9
-rw-r--r--avx512-0037785/compiler/msg/errores.msg4
-rw-r--r--avx512-0037785/compiler/msg/errorf.msg2
-rw-r--r--avx512-0037785/compiler/msg/errorfi.msg4
-rw-r--r--avx512-0037785/compiler/msg/errorhe.msg2
-rw-r--r--avx512-0037785/compiler/msg/errorheu.msg4
-rw-r--r--avx512-0037785/compiler/msg/errorid.msg4
-rw-r--r--avx512-0037785/compiler/msg/erroriu.msg2
-rw-r--r--avx512-0037785/compiler/msg/errorn.msg4
-rw-r--r--avx512-0037785/compiler/msg/errorpl.msg2
-rw-r--r--avx512-0037785/compiler/msg/errorpli.msg2
-rw-r--r--avx512-0037785/compiler/msg/errorpt.msg2
-rw-r--r--avx512-0037785/compiler/msg/errorptu.msg4
-rw-r--r--avx512-0037785/compiler/msg/errorr.msg2
-rw-r--r--avx512-0037785/compiler/msg/errorru.msg4
-rw-r--r--avx512-0037785/compiler/msg/errorues.msg4
-rw-r--r--avx512-0037785/compiler/msgidx.inc5
-rw-r--r--avx512-0037785/compiler/msgtxt.inc1290
-rw-r--r--avx512-0037785/compiler/nadd.pas3
-rw-r--r--avx512-0037785/compiler/nbas.pas4
-rw-r--r--avx512-0037785/compiler/ncal.pas3
-rw-r--r--avx512-0037785/compiler/ncginl.pas1
-rw-r--r--avx512-0037785/compiler/ncgvmt.pas2
-rw-r--r--avx512-0037785/compiler/ncnv.pas10
-rw-r--r--avx512-0037785/compiler/ncon.pas2
-rw-r--r--avx512-0037785/compiler/nflw.pas16
-rw-r--r--avx512-0037785/compiler/ngtcon.pas32
-rw-r--r--avx512-0037785/compiler/nmem.pas21
-rw-r--r--avx512-0037785/compiler/ogbase.pas2
-rw-r--r--avx512-0037785/compiler/ogomf.pas23
-rw-r--r--avx512-0037785/compiler/options.pas13
-rw-r--r--avx512-0037785/compiler/optloop.pas2
-rw-r--r--avx512-0037785/compiler/pdecsub.pas107
-rw-r--r--avx512-0037785/compiler/pgenutil.pas8
-rw-r--r--avx512-0037785/compiler/psabiehpi.pas14
-rw-r--r--avx512-0037785/compiler/psub.pas2
-rw-r--r--avx512-0037785/compiler/rgobj.pas14
-rw-r--r--avx512-0037785/compiler/scandir.pas2
-rw-r--r--avx512-0037785/compiler/scanner.pas10
-rw-r--r--avx512-0037785/compiler/symdef.pas2
-rw-r--r--avx512-0037785/compiler/systems.pas2
-rw-r--r--avx512-0037785/compiler/systems/t_amiga.pas2
-rw-r--r--avx512-0037785/compiler/systems/t_bsd.pas2
-rw-r--r--avx512-0037785/compiler/systems/t_darwin.pas5
-rw-r--r--avx512-0037785/compiler/systems/t_embed.pas118
-rw-r--r--avx512-0037785/compiler/systems/t_freertos.pas10
-rw-r--r--avx512-0037785/compiler/systems/t_win.pas2
-rw-r--r--avx512-0037785/compiler/systems/t_win16.pas3
-rw-r--r--avx512-0037785/compiler/utils/Makefile208
-rw-r--r--avx512-0037785/compiler/utils/Makefile.fpc2
-rw-r--r--avx512-0037785/compiler/utils/mkx86inl.pp90
-rw-r--r--avx512-0037785/compiler/utils/mkz80ins.pp33
-rw-r--r--avx512-0037785/compiler/utils/msg2inc.pp63
-rw-r--r--avx512-0037785/compiler/utils/ppuutils/ppudump.pp3
-rw-r--r--avx512-0037785/compiler/verbose.pas2
-rw-r--r--avx512-0037785/compiler/x86/aasmcpu.pas23
-rw-r--r--avx512-0037785/compiler/x86/agx86nsm.pas6
-rw-r--r--avx512-0037785/compiler/x86/aoptx86.pas780
-rw-r--r--avx512-0037785/compiler/x86/cgx86.pas25
-rw-r--r--avx512-0037785/compiler/x86/cx86mminnr.inc4
-rw-r--r--avx512-0037785/compiler/x86/nx86inl.pas4
-rw-r--r--avx512-0037785/compiler/x86/nx86mat.pas9
-rw-r--r--avx512-0037785/compiler/x86/nx86set.pas2
-rw-r--r--avx512-0037785/compiler/x86/rax86.pas2
-rw-r--r--avx512-0037785/compiler/x86_64/aoptcpu.pas2
-rw-r--r--avx512-0037785/compiler/x86_64/cpuelf.pas6
-rw-r--r--avx512-0037785/compiler/x86_64/cpupara.pas9
-rw-r--r--avx512-0037785/compiler/x86_64/nx64mat.pas21
-rw-r--r--avx512-0037785/packages/fcl-base/src/bufstream.pp2
-rw-r--r--avx512-0037785/packages/fcl-base/src/eventlog.pp64
-rw-r--r--avx512-0037785/packages/fcl-db/src/sqldb/interbase/ibconnection.pp16
-rw-r--r--avx512-0037785/packages/fcl-db/src/sqldb/mysql/mysqlconn.inc2
-rw-r--r--avx512-0037785/packages/fcl-db/src/sqldb/sqldb.pp10
-rw-r--r--avx512-0037785/packages/fcl-net/src/netdb.pp1117
-rw-r--r--avx512-0037785/packages/fcl-net/tests/netdbtest.pp4615
-rw-r--r--avx512-0037785/packages/fcl-net/tests/tresolvertests.pp28
-rw-r--r--avx512-0037785/packages/fcl-passrc/src/pasresolver.pp125
-rw-r--r--avx512-0037785/packages/fcl-passrc/src/pparser.pp44
-rw-r--r--avx512-0037785/packages/fcl-passrc/tests/tcresolver.pas56
-rw-r--r--avx512-0037785/packages/fcl-registry/fpmake.pp3
-rw-r--r--avx512-0037785/packages/fcl-registry/src/regini.inc45
-rw-r--r--avx512-0037785/packages/fcl-registry/src/registry.pp22
-rw-r--r--avx512-0037785/packages/fcl-registry/src/winreg.inc21
-rw-r--r--avx512-0037785/packages/fcl-registry/src/xmlreg.pp16
-rw-r--r--avx512-0037785/packages/fcl-registry/tests/Makefile208
-rw-r--r--avx512-0037785/packages/fcl-registry/tests/Makefile.fpc4
-rw-r--r--avx512-0037785/packages/fcl-registry/tests/regtcxmlreg.pp (renamed from avx512-0037785/packages/fcl-registry/tests/tcxmlreg.pp)9
-rw-r--r--avx512-0037785/packages/fcl-registry/tests/regtestbasics.pp (renamed from avx512-0037785/packages/fcl-registry/tests/testbasics.pp)18
-rw-r--r--avx512-0037785/packages/fcl-registry/tests/tregistry2.pp195
-rw-r--r--avx512-0037785/packages/fcl-registry/tests/tregtestframework.pp (renamed from avx512-0037785/packages/fcl-registry/tests/regtestframework.pp)69
-rw-r--r--avx512-0037785/packages/fcl-stl/src/gdeque.pp113
-rw-r--r--avx512-0037785/packages/fpmkunit/src/fpmkunit.pp106
-rw-r--r--avx512-0037785/packages/fv/src/views.pas3
-rw-r--r--avx512-0037785/packages/pasjpeg/examples/demo.lpi53
-rw-r--r--avx512-0037785/packages/pasjpeg/examples/example.pas40
-rw-r--r--avx512-0037785/packages/pastojs/src/fppas2js.pp264
-rw-r--r--avx512-0037785/packages/pastojs/src/pas2jsfiler.pp72
-rw-r--r--avx512-0037785/packages/pastojs/src/pas2jspcucompiler.pp1
-rw-r--r--avx512-0037785/packages/pastojs/tests/tcmodules.pas213
-rw-r--r--avx512-0037785/packages/rtl-extra/fpmake.pp12
-rw-r--r--avx512-0037785/packages/rtl-extra/src/bsd/osdefs.inc5
-rw-r--r--avx512-0037785/packages/rtl-objpas/src/inc/dateutil.inc2
-rw-r--r--avx512-0037785/packages/rtl-objpas/src/inc/variants.pp4
-rw-r--r--avx512-0037785/rtl/amiga/powerpc/execf.inc6
-rw-r--r--avx512-0037785/rtl/i386/cpu.pp24
-rw-r--r--avx512-0037785/rtl/linux/i386/si_prc.inc6
-rw-r--r--avx512-0037785/rtl/linux/linux.pp80
-rw-r--r--avx512-0037785/rtl/linux/m68k/cprt0.as1
-rw-r--r--avx512-0037785/rtl/linux/m68k/dllprt0.as1
-rw-r--r--avx512-0037785/rtl/linux/mips/cprt0.as5
-rw-r--r--avx512-0037785/rtl/linux/mips/prt0.as1
-rw-r--r--avx512-0037785/rtl/linux/si_impl.inc2
-rw-r--r--avx512-0037785/rtl/linux/system.pp10
-rw-r--r--avx512-0037785/rtl/linux/x86_64/si_prc.inc10
-rw-r--r--avx512-0037785/rtl/linux/x86_64/syscall.inc24
-rw-r--r--avx512-0037785/rtl/objpas/sysconst.pp4
-rw-r--r--avx512-0037785/rtl/objpas/sysutils/syshelpo.inc10
-rw-r--r--avx512-0037785/rtl/unix/oscdeclh.inc4
-rw-r--r--avx512-0037785/rtl/unix/sysutils.pp168
-rw-r--r--avx512-0037785/tests/Makefile4
-rw-r--r--avx512-0037785/tests/Makefile.fpc4
-rw-r--r--avx512-0037785/tests/test/cg/tpara4.pp22
-rw-r--r--avx512-0037785/tests/test/theapthread.pp11
-rw-r--r--avx512-0037785/tests/test/units/linux/tfutimesen.pp84
-rw-r--r--avx512-0037785/tests/test/units/linux/tstatx.pp16
-rw-r--r--avx512-0037785/tests/test/units/linux/tutimensat.pp83
-rw-r--r--avx512-0037785/tests/test/units/sysutils/tfile1.pp13
-rw-r--r--avx512-0037785/tests/test/units/sysutils/tfileage.pp18
-rw-r--r--avx512-0037785/tests/utils/testsuite/utests.pp391
-rw-r--r--avx512-0037785/tests/webtbf/tw24434.pp13
-rw-r--r--avx512-0037785/tests/webtbf/tw37217.pp12
-rw-r--r--avx512-0037785/tests/webtbf/tw38287.pp11
-rw-r--r--avx512-0037785/tests/webtbs/tw32139.pp11
-rw-r--r--avx512-0037785/tests/webtbs/tw34027.pp27
-rw-r--r--avx512-0037785/tests/webtbs/tw37060.pp8
-rw-r--r--avx512-0037785/tests/webtbs/tw38306.pp39
-rw-r--r--avx512-0037785/tests/webtbs/tw38316.pp21
-rw-r--r--avx512-0037785/tests/webtbs/tw38337.pp20
-rw-r--r--avx512-0037785/tests/webtbs/tw38339.pp23
-rw-r--r--avx512-0037785/tests/webtbs/tw38351.pp33
-rw-r--r--avx512-0037785/tests/webtbs/tw38385.pp41
-rw-r--r--avx512-0037785/tests/webtbs/tw38390.pp23
-rw-r--r--avx512-0037785/tests/webtbs/tw38412.pp10
-rw-r--r--avx512-0037785/tests/webtbs/tw38413.pp12
-rw-r--r--avx512-0037785/tests/webtbs/tw38429.pp61
-rw-r--r--avx512-0037785/tests/webtbs/uw38385a.pp17
-rw-r--r--avx512-0037785/tests/webtbs/uw38385b.pp18
-rw-r--r--avx512-0037785/tests/webtbs/uw38385c.pp18
-rw-r--r--avx512-0037785/tests/webtbs/uw38429.pp88
-rw-r--r--avx512-0037785/utils/fpdoc/dglobals.pp248
-rw-r--r--avx512-0037785/utils/fpdoc/dw_basehtml.pp20
-rw-r--r--avx512-0037785/utils/fpdoc/dw_basemd.pp12
-rw-r--r--avx512-0037785/utils/fpdoc/dw_chm.pp24
-rw-r--r--avx512-0037785/utils/fpdoc/dw_dxml.pp4
-rw-r--r--avx512-0037785/utils/fpdoc/dw_html.pp128
-rw-r--r--avx512-0037785/utils/fpdoc/dw_ipflin.pas2
-rw-r--r--avx512-0037785/utils/fpdoc/dw_latex.pp4
-rw-r--r--avx512-0037785/utils/fpdoc/dw_linrtf.pp4
-rw-r--r--avx512-0037785/utils/fpdoc/dw_man.pp7
-rw-r--r--avx512-0037785/utils/fpdoc/dw_markdown.pp38
-rw-r--r--avx512-0037785/utils/fpdoc/dw_txt.pp4
-rw-r--r--avx512-0037785/utils/fpdoc/dw_xml.pp11
-rw-r--r--avx512-0037785/utils/fpdoc/dwlinear.pp7
-rw-r--r--avx512-0037785/utils/fpdoc/dwriter.pp223
-rw-r--r--avx512-0037785/utils/fpdoc/fpclasschart.pp14
-rw-r--r--avx512-0037785/utils/fpdoc/fpdoc.lpi16
-rw-r--r--avx512-0037785/utils/fpdoc/fpdoc.pp28
-rw-r--r--avx512-0037785/utils/fpdoc/fpdocclasstree.pp84
-rw-r--r--avx512-0037785/utils/fpdoc/fpdocproj.pas11
-rw-r--r--avx512-0037785/utils/fpdoc/fpdocstrs.pp256
-rw-r--r--avx512-0037785/utils/fpdoc/fpdocxmlopts.pas11
-rw-r--r--avx512-0037785/utils/fpdoc/fpmake.pp10
-rw-r--r--avx512-0037785/utils/fpdoc/makeskel.pp2
-rw-r--r--avx512-0037785/utils/fpdoc/mkfpdoc.pp86
-rw-r--r--avx512-0037785/utils/pas2js/dist/rtl.js18
218 files changed, 11111 insertions, 2698 deletions
diff --git a/avx512-0037785/compiler/Makefile b/avx512-0037785/compiler/Makefile
index 3bf6972579..950d084474 100644
--- a/avx512-0037785/compiler/Makefile
+++ b/avx512-0037785/compiler/Makefile
@@ -4640,6 +4640,9 @@ ifdef CMP
override DIFF:=$(CMP) -i218
endif
endif
+ifeq ($(OS_TARGET), darwin)
+CODESIGN?=$(strip $(wildcard $(addsuffix /codesign,$(SEARCHPATH))))
+endif
ifneq ($(CYCLELEVEL),1)
ifndef ALLOW_WARNINGS
override LOCALOPT+=-Sew
@@ -4941,7 +4944,11 @@ ifdef OLDFPC
ifneq ($(OS_TARGET),darwin)
DIFFRESULT:=$(shell $(DIFF) $(OLDFPC) $(FPC))
else
-DIFFRESULT:=$(shell cp $(OLDFPC) $(OLDFPC).tmp; cp $(FPC) $(FPC).tmp; strip -no_uuid $(OLDFPC).tmp; strip -no_uuid $(FPC).tmp; $(DIFF) $(OLDFPC).tmp $(FPC).tmp; rm $(OLDFPC).tmp $(FPC).tmp)
+ifneq ($(CODESIGN),)
+DIFFRESULT:=$(shell $(COPY) $(OLDFPC) $(OLDFPC).tmp; $(COPY) $(FPC) $(FPC).tmp; strip -no_uuid $(OLDFPC).tmp; strip -no_uuid $(FPC).tmp; $(CODESIGN) --remove-signature $(OLDFPC).tmp; codesign --remove-signature $(FPC).tmp; $(DIFF) $(OLDFPC).tmp $(FPC).tmp; $(RMPROG) $(OLDFPC).tmp $(FPC).tmp)
+else
+DIFFRESULT:=$(shell $(COPY) $(OLDFPC) $(OLDFPC).tmp; $(COPY) $(FPC) $(FPC).tmp; strip -no_uuid $(OLDFPC).tmp; strip -no_uuid $(FPC).tmp; $(DIFF) $(OLDFPC).tmp $(FPC).tmp; $(RMPROG) $(OLDFPC).tmp $(FPC).tmp)
+endif
endif
else
DIFFRESULT=Not equal
@@ -4980,7 +4987,20 @@ endif
$(MAKE) tempclean
$(MAKE) $(TEMPNAME3)
$(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME3PREFIX)$(TEMPNAME3)' 'OLDFPC=$(BASEDIR)/$(TEMPNAME2)' next CYCLELEVEL=4
+ifneq ($(OS_TARGET), darwin)
$(DIFF) $(TEMPNAME3) $(EXENAME)
+else
+ $(COPY) $(TEMPNAME3) $(TEMPNAME3).tmp
+ $(COPY) $(EXENAME) $(EXENAME).tmp
+ strip -no_uuid $(TEMPNAME3).tmp
+ strip -no_uuid $(EXENAME).tmp
+ifneq ($(CODESIGN),)
+ $(CODESIGN) --remove-signature $(TEMPNAME3).tmp
+ $(CODESIGN) --remove-signature $(EXENAME).tmp
+endif
+ $(DIFF) $(TEMPNAME3).tmp $(EXENAME).tmp
+ rm $(TEMPNAME3).tmp $(EXENAME).tmp
+endif
$(MAKE) $(addsuffix _all,$(TARGET_DIRS)) 'FPC=$(BASEDIR)/$(EXENAMEPREFIX)$(EXENAME)'
$(MAKE) wpocycle
$(MAKE) echotime
diff --git a/avx512-0037785/compiler/Makefile.fpc b/avx512-0037785/compiler/Makefile.fpc
index a3852109dc..f1c6e501d2 100644
--- a/avx512-0037785/compiler/Makefile.fpc
+++ b/avx512-0037785/compiler/Makefile.fpc
@@ -438,6 +438,10 @@ override DIFF:=$(CMP) -i218
endif
endif
+ifeq ($(OS_TARGET), darwin)
+CODESIGN?=$(strip $(wildcard $(addsuffix /codesign,$(SEARCHPATH))))
+endif
+
# Use -Sew option by default
# Allow disabling by setting ALLOW_WARNINGS=1
ifneq ($(CYCLELEVEL),1)
@@ -878,7 +882,11 @@ ifdef OLDFPC
ifneq ($(OS_TARGET),darwin)
DIFFRESULT:=$(shell $(DIFF) $(OLDFPC) $(FPC))
else
-DIFFRESULT:=$(shell cp $(OLDFPC) $(OLDFPC).tmp; cp $(FPC) $(FPC).tmp; strip -no_uuid $(OLDFPC).tmp; strip -no_uuid $(FPC).tmp; $(DIFF) $(OLDFPC).tmp $(FPC).tmp; rm $(OLDFPC).tmp $(FPC).tmp)
+ifneq ($(CODESIGN),)
+DIFFRESULT:=$(shell $(COPY) $(OLDFPC) $(OLDFPC).tmp; $(COPY) $(FPC) $(FPC).tmp; strip -no_uuid $(OLDFPC).tmp; strip -no_uuid $(FPC).tmp; $(CODESIGN) --remove-signature $(OLDFPC).tmp; codesign --remove-signature $(FPC).tmp; $(DIFF) $(OLDFPC).tmp $(FPC).tmp; $(RMPROG) $(OLDFPC).tmp $(FPC).tmp)
+else
+DIFFRESULT:=$(shell $(COPY) $(OLDFPC) $(OLDFPC).tmp; $(COPY) $(FPC) $(FPC).tmp; strip -no_uuid $(OLDFPC).tmp; strip -no_uuid $(FPC).tmp; $(DIFF) $(OLDFPC).tmp $(FPC).tmp; $(RMPROG) $(OLDFPC).tmp $(FPC).tmp)
+endif
endif
else
DIFFRESULT=Not equal
@@ -922,7 +930,20 @@ endif
$(MAKE) tempclean
$(MAKE) $(TEMPNAME3)
$(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME3PREFIX)$(TEMPNAME3)' 'OLDFPC=$(BASEDIR)/$(TEMPNAME2)' next CYCLELEVEL=4
+ifneq ($(OS_TARGET), darwin)
$(DIFF) $(TEMPNAME3) $(EXENAME)
+else
+ $(COPY) $(TEMPNAME3) $(TEMPNAME3).tmp
+ $(COPY) $(EXENAME) $(EXENAME).tmp
+ strip -no_uuid $(TEMPNAME3).tmp
+ strip -no_uuid $(EXENAME).tmp
+ifneq ($(CODESIGN),)
+ $(CODESIGN) --remove-signature $(TEMPNAME3).tmp
+ $(CODESIGN) --remove-signature $(EXENAME).tmp
+endif
+ $(DIFF) $(TEMPNAME3).tmp $(EXENAME).tmp
+ rm $(TEMPNAME3).tmp $(EXENAME).tmp
+endif
$(MAKE) $(addsuffix _all,$(TARGET_DIRS)) 'FPC=$(BASEDIR)/$(EXENAMEPREFIX)$(EXENAME)'
$(MAKE) wpocycle
$(MAKE) echotime
diff --git a/avx512-0037785/compiler/aarch64/aasmcpu.pas b/avx512-0037785/compiler/aarch64/aasmcpu.pas
index ba8e3001be..49e66eb606 100644
--- a/avx512-0037785/compiler/aarch64/aasmcpu.pas
+++ b/avx512-0037785/compiler/aarch64/aasmcpu.pas
@@ -1018,6 +1018,7 @@ implementation
A_TST,
A_FCMP,A_FCMPE,
A_CBZ,A_CBNZ,
+ A_PRFM,A_PRFUM,
A_RET:
result:=operand_read;
A_STR,A_STUR:
@@ -1026,14 +1027,6 @@ implementation
else
{ check for pre/post indexed in spilling_get_operation_type_ref }
result:=operand_read;
- A_STLXP,
- A_STLXR,
- A_STXP,
- A_STXR:
- if opnr=0 then
- result:=operand_write
- else
- result:=operand_read;
A_STP:
begin
if opnr in [0,1] then
@@ -1102,12 +1095,21 @@ implementation
A_FCVTZS,
A_SDIV,
A_SMULL,
+ A_STLXP,
+ A_STLXR,
+ A_STXP,
+ A_STXR,
A_SUB,
+ A_SXTB,
+ A_SXTH,
+ A_SXTW,
A_UBFIZ,
A_UBFX,
A_UCVTF,
A_UDIV,
- A_UMULL:
+ A_UMULL,
+ A_UXTB,
+ A_UXTH:
if opnr=0 then
result:=operand_write
else
diff --git a/avx512-0037785/compiler/aarch64/agcpugas.pas b/avx512-0037785/compiler/aarch64/agcpugas.pas
index 35eafef1e7..d6fd59ac76 100644
--- a/avx512-0037785/compiler/aarch64/agcpugas.pas
+++ b/avx512-0037785/compiler/aarch64/agcpugas.pas
@@ -252,7 +252,6 @@ unit agcpugas;
lastsym : tai_symbol;
lastsec : tai_section;
inprologue,
- inhandlerdata,
deleteai : boolean;
totalcount,
instrcount,
@@ -265,7 +264,6 @@ unit agcpugas;
sehlist,
tmplist : TAsmList;
xdatasym : tasmsymbol;
- unwindread,
unwindrec : longword;
begin
if not assigned(list) then
@@ -278,7 +276,6 @@ unit agcpugas;
instrcount:=0;
datacount:=0;
unwinddata:=nil;
- inhandlerdata:=false;
inprologue:=false;
handlerdata:=nil;
handlerdataidx:=0;
diff --git a/avx512-0037785/compiler/aarch64/aoptcpu.pas b/avx512-0037785/compiler/aarch64/aoptcpu.pas
index e682bbdda7..4ef898284e 100644
--- a/avx512-0037785/compiler/aarch64/aoptcpu.pas
+++ b/avx512-0037785/compiler/aarch64/aoptcpu.pas
@@ -568,7 +568,6 @@ Implementation
ThisRegister: TRegister;
OffsetVal, ValidOffset, MinOffset, MaxOffset: asizeint;
TargetOpcode: TAsmOp;
- Breakout: Boolean;
begin
Result := False;
ThisRegister := taicpu(p).oper[0]^.reg;
@@ -621,8 +620,6 @@ Implementation
if (taicpu(hp1).opcode = taicpu(p).opcode) then
begin
- Breakout := False;
-
if (taicpu(hp1).oppostfix = PF_NONE) and
{ Registers need to be the same size }
(getsubreg(ThisRegister) = getsubreg(taicpu(hp1).oper[0]^.reg)) and
@@ -754,8 +751,6 @@ Implementation
function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
- var
- hp1: tai;
begin
result := false;
if p.typ=ait_instruction then
@@ -817,8 +812,6 @@ Implementation
function TCpuAsmOptimizer.PeepHoleOptPass2Cpu(var p: tai): boolean;
- var
- hp1: tai;
begin
result := false;
if p.typ=ait_instruction then
diff --git a/avx512-0037785/compiler/aarch64/cgcpu.pas b/avx512-0037785/compiler/aarch64/cgcpu.pas
index 9f0917e5a7..2036e99534 100644
--- a/avx512-0037785/compiler/aarch64/cgcpu.pas
+++ b/avx512-0037785/compiler/aarch64/cgcpu.pas
@@ -587,6 +587,9 @@ implementation
manipulated_a: tcgint;
leftover_a: word;
begin
+{$ifdef extdebug}
+ list.concat(tai_comment.Create(strpnew('Generating constant ' + tostr(a))));
+{$endif extdebug}
case a of
{ Small positive number }
$0..$FFFF:
diff --git a/avx512-0037785/compiler/aasmcnst.pas b/avx512-0037785/compiler/aasmcnst.pas
index 4d106564fa..d37cd74b76 100644
--- a/avx512-0037785/compiler/aasmcnst.pas
+++ b/avx512-0037785/compiler/aasmcnst.pas
@@ -427,6 +427,10 @@ type
function queue_subscriptn_multiple_by_name(def: tabstractrecorddef; const fields: array of TIDString): tdef;
{ queue a type conversion operation }
procedure queue_typeconvn(fromdef, todef: tdef); virtual;
+ { queue a add operation }
+ procedure queue_addn(def: tdef; const index: tconstexprint); virtual;
+ { queue a sub operation }
+ procedure queue_subn(def: tdef; const index: tconstexprint); virtual;
{ finalise the queue (so a new one can be created) and flush the
previously queued operations, applying them in reverse order on a...}
{ ... procdef }
@@ -2080,6 +2084,18 @@ implementation
end;
+ procedure ttai_typedconstbuilder.queue_addn(def: tdef; const index: tconstexprint);
+ begin
+ inc(fqueue_offset,def.size*int64(index));
+ end;
+
+
+ procedure ttai_typedconstbuilder.queue_subn(def: tdef; const index: tconstexprint);
+ begin
+ dec(fqueue_offset,def.size*int64(index));
+ end;
+
+
procedure ttai_typedconstbuilder.queue_subscriptn(def: tabstractrecorddef; vs: tfieldvarsym);
begin
inc(fqueue_offset,vs.fieldoffset);
diff --git a/avx512-0037785/compiler/aggas.pas b/avx512-0037785/compiler/aggas.pas
index efd565fdc3..710ec54652 100644
--- a/avx512-0037785/compiler/aggas.pas
+++ b/avx512-0037785/compiler/aggas.pas
@@ -497,7 +497,6 @@ implementation
procedure TGNUAssembler.WriteSection(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder;secalign:longint;secflags:TSectionFlags=[];secprogbits:TSectionProgbits=SPB_None);
var
s : string;
- secflag: TSectionFlag;
usesectionprogbits,
usesectionflags: boolean;
begin
diff --git a/avx512-0037785/compiler/aoptobj.pas b/avx512-0037785/compiler/aoptobj.pas
index fd14f81674..8b10fd0091 100644
--- a/avx512-0037785/compiler/aoptobj.pas
+++ b/avx512-0037785/compiler/aoptobj.pas
@@ -1382,12 +1382,10 @@ Unit AoptObj;
removedSomething := false;
firstRemovedWasAlloc := false;
{$ifdef allocregdebug}
- hp := tai_comment.Create(strpnew('allocating '+std_regname(newreg(R_INTREGISTER,supreg,R_SUBWHOLE))+
- ' from here...'));
- insertllitem(asml,p1.previous,p1,hp);
- hp := tai_comment.Create(strpnew('allocated '+std_regname(newreg(R_INTREGISTER,supreg,R_SUBWHOLE))+
- ' till here...'));
- insertllitem(asml,p2,p2.next,hp);
+ hp := tai_comment.Create(strpnew('allocating '+std_regname(reg)+' from here...'));
+ insertllitem(p1.previous,p1,hp);
+ hp := tai_comment.Create(strpnew('allocated '+std_regname(reg)+' till here...'));
+ insertllitem(p2,p2.next,hp);
{$endif allocregdebug}
{ do it the safe way: always allocate the full super register,
as we do no register re-allocation in the peephole optimizer,
diff --git a/avx512-0037785/compiler/arm/aoptcpu.pas b/avx512-0037785/compiler/arm/aoptcpu.pas
index 3adb81644e..2b798b18c9 100644
--- a/avx512-0037785/compiler/arm/aoptcpu.pas
+++ b/avx512-0037785/compiler/arm/aoptcpu.pas
@@ -59,6 +59,7 @@ Type
function InstructionLoadsFromReg(const reg : TRegister; const hp : tai) : boolean; override;
function RegLoadedWithNewValue(reg : tregister; hp : tai) : boolean; override;
+ function OptPass1And(var p: tai): Boolean; override; { There's optimisation code that's general for all ARM platforms }
protected
function LookForPreindexedPattern(p: taicpu): boolean;
function LookForPostindexedPattern(p: taicpu): boolean;
@@ -67,7 +68,6 @@ Type
{ Individual optimisation routines }
function OptPass1DataCheckMov(var p: tai): Boolean;
function OptPass1ADDSUB(var p: tai): Boolean;
- function OptPass1And(var p: tai): Boolean; override; { There's optimisation code that's general for all ARM platforms }
function OptPass1CMP(var p: tai): Boolean;
function OptPass1LDR(var p: tai): Boolean;
function OptPass1STM(var p: tai): Boolean;
@@ -540,7 +540,6 @@ Implementation
function TCpuAsmOptimizer.OptPass1ADDSUB(var p: tai): Boolean;
var
hp1,hp2: tai;
- oldreg: tregister;
begin
Result := OptPass1DataCheckMov(p);
@@ -621,7 +620,7 @@ Implementation
function TCpuAsmOptimizer.OptPass1MUL(var p: tai): Boolean;
var
- hp1,hp2: tai;
+ hp1: tai;
oldreg: tregister;
begin
Result := OptPass1DataCheckMov(p);
@@ -1099,7 +1098,7 @@ Implementation
function TCpuAsmOptimizer.OptPass1MOV(var p: tai): Boolean;
var
- hp1, hpfar1, hp2, hp3: tai;
+ hp1, hpfar1, hp2: tai;
i, i2: longint;
tempop: tasmop;
dealloc: tai_regalloc;
diff --git a/avx512-0037785/compiler/armgen/aoptarm.pas b/avx512-0037785/compiler/armgen/aoptarm.pas
index 2581f34a5b..b0f3b0f0ae 100644
--- a/avx512-0037785/compiler/armgen/aoptarm.pas
+++ b/avx512-0037785/compiler/armgen/aoptarm.pas
@@ -531,6 +531,11 @@ Implementation
{ Instruction will become mov r1,r1 }
DebugMsg('Peephole Optimization: Mov2None 2 done', next_hp);
+ { Allocate r1 between the instructions; not doing
+ so may cause problems when removing superfluous
+ MOVs later (i38055) }
+ AllocRegBetween(taicpu(p).oper[1]^.reg, p, next_hp, UsedRegs);
+
if (next_hp = hp1) then
{ Don't let hp1 become a dangling pointer }
hp1 := nil;
@@ -902,8 +907,8 @@ Implementation
{ reg1 might not be modified inbetween }
not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then
begin
- DebugMsg('Peephole SxtbAndImm2Sxtb done', p);
- taicpu(hp1).opcode:=A_SXTB;
+ DebugMsg('Peephole SxtbAndImm2Uxtb done', p);
+ taicpu(hp1).opcode:=A_UXTB;
taicpu(hp1).ops:=2;
taicpu(hp1).loadReg(1,taicpu(p).oper[1]^.reg);
GetNextInstruction(p,hp2);
@@ -913,7 +918,7 @@ Implementation
result:=true;
end
else if GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
- RemoveSuperfluousMove(p, hp1, 'SxtbMov2Data') then
+ RemoveSuperfluousMove(p, hp1, 'UxtbMov2Data') then
Result:=true;
end;
@@ -983,7 +988,7 @@ Implementation
and reg3,reg2,#65535
dealloc reg2
to
- sxth reg3,reg1
+ uxth reg3,reg1
}
else if MatchInstruction(p, A_SXTH, [C_None], [PF_None]) and
(taicpu(p).ops=2) and
@@ -997,8 +1002,8 @@ Implementation
{ reg1 might not be modified inbetween }
not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then
begin
- DebugMsg('Peephole SxthAndImm2Sxth done', p);
- taicpu(hp1).opcode:=A_SXTH;
+ DebugMsg('Peephole SxthAndImm2Uxth done', p);
+ taicpu(hp1).opcode:=A_UXTH;
taicpu(hp1).ops:=2;
taicpu(hp1).loadReg(1,taicpu(p).oper[1]^.reg);
GetNextInstruction(p, hp1);
@@ -1008,7 +1013,7 @@ Implementation
result:=true;
end
else if GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
- RemoveSuperfluousMove(p, hp1, 'SxthMov2Data') then
+ RemoveSuperfluousMove(p, hp1, 'UxthMov2Data') then
Result:=true;
end;
diff --git a/avx512-0037785/compiler/avr/agavrgas.pas b/avx512-0037785/compiler/avr/agavrgas.pas
index fc62854f69..d4df03db2a 100644
--- a/avx512-0037785/compiler/avr/agavrgas.pas
+++ b/avx512-0037785/compiler/avr/agavrgas.pas
@@ -154,8 +154,6 @@ unit agavrgas;
function getopstr(const o:toper) : string;
var
hs : string;
- first : boolean;
- r : tsuperregister;
begin
case o.typ of
top_reg:
diff --git a/avx512-0037785/compiler/avr/aoptcpu.pas b/avx512-0037785/compiler/avr/aoptcpu.pas
index 031633d92f..3a99b9864b 100644
--- a/avx512-0037785/compiler/avr/aoptcpu.pas
+++ b/avx512-0037785/compiler/avr/aoptcpu.pas
@@ -258,7 +258,6 @@ Implementation
var
hp1, hp2, hp3: tai;
- s: string;
begin
result:=false;
diff --git a/avx512-0037785/compiler/avr/cgcpu.pas b/avx512-0037785/compiler/avr/cgcpu.pas
index 4722405541..72402d6552 100644
--- a/avx512-0037785/compiler/avr/cgcpu.pas
+++ b/avx512-0037785/compiler/avr/cgcpu.pas
@@ -264,7 +264,6 @@ unit cgcpu;
var
i,j : longint;
hp : PCGParaLocation;
- ref: treference;
tmpreg: TRegister;
begin
if not(tcgsize2size[paraloc.Size] in [1..4]) then
@@ -310,7 +309,7 @@ unit cgcpu;
procedure tcgavr.a_load_ref_cgpara(list : TAsmList;size : tcgsize;const r : treference;const paraloc : TCGPara);
var
- tmpref, ref: treference;
+ tmpref: treference;
location: pcgparalocation;
sizeleft: tcgint;
i: Integer;
@@ -327,7 +326,6 @@ unit cgcpu;
a_load_ref_reg(list,location^.size,location^.size,tmpref,location^.register);
LOC_REFERENCE:
begin
- ref:=tmpref;
for i:=1 to sizeleft do
begin
tmpreg:=getintregister(list,OS_8);
@@ -417,7 +415,7 @@ unit cgcpu;
procedure tcgavr.a_op_const_reg_reg_internal(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src,srchi,dst,dsthi: tregister);
var
- tmpSrc, tmpDst, countreg: TRegister;
+ countreg: TRegister;
b, b2, i, j: byte;
s1, s2, t1: integer;
l1: TAsmLabel;
@@ -574,10 +572,7 @@ unit cgcpu;
countreg,
tmpreg: tregister;
i : integer;
- instr : taicpu;
- paraloc1,paraloc2 : TCGPara;
l1,l2 : tasmlabel;
- pd : tprocdef;
hovloc: tlocation;
{ NextRegDst* is sometimes called before the register usage and sometimes afterwards }
@@ -1093,7 +1088,6 @@ unit cgcpu;
function tcgavr.normalize_ref(list:TAsmList;ref: treference;tmpreg : tregister) : treference;
var
tmpref : treference;
- l : tasmlabel;
begin
Result:=ref;
@@ -1702,8 +1696,7 @@ unit cgcpu;
procedure tcgavr.a_cmp_const_reg_label(list : TAsmList;size : tcgsize;
cmp_op : topcmp;a : tcgint;reg : tregister;l : tasmlabel);
var
- swapped , test_msb: boolean;
- tmpreg : tregister;
+ swapped : boolean;
i : byte;
begin
if a=0 then
@@ -1856,7 +1849,7 @@ unit cgcpu;
procedure tcgavr.g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister);
var
l : TAsmLabel;
- tmpflags : TResFlags;
+ //tmpflags : TResFlags;
i: Integer;
hreg: TRegister;
begin
@@ -1889,8 +1882,8 @@ unit cgcpu;
procedure tcgavr.a_adjust_sp(list : TAsmList; value : longint);
- var
- i : integer;
+ {var
+ i : integer; }
begin
case value of
0:
@@ -2448,7 +2441,7 @@ unit cgcpu;
var
countreg,tmpreg,tmpreg2: tregister;
srcref,dstref : treference;
- copysize,countregsize : tcgsize;
+ countregsize : tcgsize;
l : TAsmLabel;
i : longint;
SrcQuickRef, DestQuickRef : Boolean;
@@ -2464,7 +2457,6 @@ unit cgcpu;
dstref.base:=NR_R26;
dstref.addressmode:=AM_POSTINCREMENT;
- copysize:=OS_8;
if len<256 then
countregsize:=OS_8
else if len<65536 then
diff --git a/avx512-0037785/compiler/avr/cpupara.pas b/avx512-0037785/compiler/avr/cpupara.pas
index 597c493328..45d6cd1c19 100644
--- a/avx512-0037785/compiler/avr/cpupara.pas
+++ b/avx512-0037785/compiler/avr/cpupara.pas
@@ -201,7 +201,6 @@ unit cpupara;
paracgsize : tcgsize;
paralen : longint;
i : integer;
- firstparaloc: boolean;
procedure assignintreg;
begin
@@ -300,7 +299,6 @@ unit cpupara;
if paralen=0 then
internalerror(200410311);
{$endif EXTDEBUG}
- firstparaloc:=true;
if loc=LOC_REGISTER then
begin
{ the lsb is located in the register with the lowest number,
@@ -386,7 +384,6 @@ unit cpupara;
inc(paraloc^.reference.offset,2);
end;
end;
- firstparaloc:=false;
end;
end;
curfloatreg:=nextfloatreg;
@@ -400,7 +397,6 @@ unit cpupara;
var
cur_stack_offset: aword;
curintreg, curfloatreg, curmmreg: tsuperregister;
- retcgsize : tcgsize;
begin
init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
diff --git a/avx512-0037785/compiler/avr/navradd.pas b/avx512-0037785/compiler/avr/navradd.pas
index d83c2708dd..e704557887 100644
--- a/avx512-0037785/compiler/avr/navradd.pas
+++ b/avx512-0037785/compiler/avr/navradd.pas
@@ -33,11 +33,12 @@ interface
private
function GetResFlags(unsigned:Boolean):TResFlags;
protected
- function pass_1 : tnode;override;
procedure second_cmpordinal;override;
procedure second_cmpsmallset;override;
procedure second_cmp64bit;override;
procedure second_cmp;
+ public
+ function pass_1 : tnode;override;
end;
implementation
diff --git a/avx512-0037785/compiler/avr/navrmat.pas b/avx512-0037785/compiler/avr/navrmat.pas
index 67bf632fe6..751dfc8cef 100644
--- a/avx512-0037785/compiler/avr/navrmat.pas
+++ b/avx512-0037785/compiler/avr/navrmat.pas
@@ -59,7 +59,7 @@ implementation
procedure tavrnotnode.second_boolean;
var
- tmpreg,lreg : tregister;
+ tmpreg : tregister;
i : longint;
falselabel,truelabel,skiplabel: TAsmLabel;
begin
diff --git a/avx512-0037785/compiler/avr/raavrgas.pas b/avx512-0037785/compiler/avr/raavrgas.pas
index c5b1ae5bd7..48efcd3759 100644
--- a/avx512-0037785/compiler/avr/raavrgas.pas
+++ b/avx512-0037785/compiler/avr/raavrgas.pas
@@ -326,10 +326,8 @@ Unit raavrgas;
var
tempreg : tregister;
- ireg : tsuperregister;
hl : tasmlabel;
ofs : longint;
- registerset : tcpuregisterset;
tempstr : string;
tempsymtyp : tasmsymtype;
Begin
@@ -612,18 +610,16 @@ Unit raavrgas;
function tavrattreader.is_asmopcode(const s: string):boolean;
-
+(*
const
{ sorted by length so longer postfixes will match first }
postfix2strsorted : array[1..19] of string[2] = (
'EP','SB','BT','SH',
'IA','IB','DA','DB','FD','FA','ED','EA',
'B','D','E','P','T','H','S');
-
+*)
var
- len,
- j,
- sufidx : longint;
+ j : longint;
hs : string;
maxlen : longint;
icond : tasmcond;
diff --git a/avx512-0037785/compiler/avr/rgcpu.pas b/avx512-0037785/compiler/avr/rgcpu.pas
index 667d83325a..1eb0afa659 100644
--- a/avx512-0037785/compiler/avr/rgcpu.pas
+++ b/avx512-0037785/compiler/avr/rgcpu.pas
@@ -56,8 +56,8 @@ unit rgcpu;
procedure trgcpu.add_constraints(reg:tregister);
- var
- supreg,i : Tsuperregister;
+ {var
+ supreg,i : Tsuperregister;}
begin
case getsubreg(reg) of
{ Let 64bit floats conflict with all odd float regs }
@@ -76,8 +76,8 @@ unit rgcpu;
{ Let 64bit ints conflict with all odd int regs }
R_SUBQ:
begin
- supreg:=getsupreg(reg);
{
+ supreg:=getsupreg(reg);
i:=RS_G1;
while (i<=RS_I7) do
begin
@@ -95,7 +95,6 @@ unit rgcpu;
helpins : tai;
tmpref : treference;
helplist : TAsmList;
- hreg : tregister;
begin
if (abs(spilltemp.offset)>63) or (CPUAVR_16_REGS in cpu_capabilities[current_settings.cputype]) then
begin
@@ -121,7 +120,6 @@ unit rgcpu;
var
tmpref : treference;
helplist : TAsmList;
- hreg : tregister;
begin
if (abs(spilltemp.offset)>63) or (CPUAVR_16_REGS in cpu_capabilities[current_settings.cputype]) then
begin
@@ -185,8 +183,6 @@ unit rgcpu;
function trgcpu.do_spill_replace(list:TAsmList;instr:tai_cpu_abstract_sym;orgreg:tsuperregister;const spilltemp:treference):boolean;
- var
- b : byte;
begin
result:=false;
if not(spilltemp.offset in [0..63]) or (CPUAVR_16_REGS in cpu_capabilities[current_settings.cputype]) then
diff --git a/avx512-0037785/compiler/cfidwarf.pas b/avx512-0037785/compiler/cfidwarf.pas
index 767e45f3fb..6d65387e51 100644
--- a/avx512-0037785/compiler/cfidwarf.pas
+++ b/avx512-0037785/compiler/cfidwarf.pas
@@ -435,7 +435,8 @@ implementation
end
else
begin
- tc:=tai_const.create_sym(cielabel);
+ { according to the dwarf (2 to 4) standard, this is an uword being always 32 bit unsigned }
+ tc:=tai_const.create_type_sym(aitconst_32bit,cielabel);
{ force label offset to secrel32 for windows systems }
if (target_info.system in systems_windows+systems_wince) then
tc.consttype:=aitconst_secrel32_symbol;
diff --git a/avx512-0037785/compiler/dbgcodeview.pas b/avx512-0037785/compiler/dbgcodeview.pas
index f2a3f6b6dd..814b645245 100644
--- a/avx512-0037785/compiler/dbgcodeview.pas
+++ b/avx512-0037785/compiler/dbgcodeview.pas
@@ -124,7 +124,7 @@ interface
LF_PAD10 = $fa,
LF_PAD11 = $fb,
LF_PAD12 = $fc,
- LF_PAD13 = $fc,
+ LF_PAD13 = $fd,
LF_PAD14 = $fe,
LF_PAD15 = $ff,
diff --git a/avx512-0037785/compiler/dbgstabs.pas b/avx512-0037785/compiler/dbgstabs.pas
index ef8a575475..8b26099a61 100644
--- a/avx512-0037785/compiler/dbgstabs.pas
+++ b/avx512-0037785/compiler/dbgstabs.pas
@@ -571,7 +571,7 @@ implementation
just associated to pointer types }
use_tag_prefix:=(def.typ in tagtypes) and
((def.typ<>stringdef) or
- (tstringdef(tdef).stringtype in [st_shortstring,st_longstring]));
+ (tstringdef(def).stringtype in [st_shortstring,st_longstring]));
end;
diff --git a/avx512-0037785/compiler/fpcdefs.inc b/avx512-0037785/compiler/fpcdefs.inc
index 6b762b1c50..59b4c1f240 100644
--- a/avx512-0037785/compiler/fpcdefs.inc
+++ b/avx512-0037785/compiler/fpcdefs.inc
@@ -31,6 +31,31 @@
{$define USEINLINE}
{$endif EXTDEBUG}
+{$ifdef DEBUG_ALL_OPT}
+ { for aopt unit }
+ {$define DEBUG_OPTALLOC}
+ {$define DEBUG_INSTRUCTIONREGISTERDEPENDENCIES}
+ {for CPU/aoptcpu unit }
+ {$define DEBUG_AOPTCPU}
+ {$define DEBUG_PREREGSCHEDULER (arm specific) }
+ { for aoptobj unit }
+ {$define DEBUG_AOPTOBJ}
+ {$define ALLOCREGDEBUG}
+ { for optconstprop unit }
+ {$define DEBUG_CONSTPROP}
+ { for optcse unit }
+ {$define CSEDEBUG}
+ { for optdeadstore unit }
+ {$define DEBUG_DEADSTORE}
+ { for optdfa unit }
+ {$define DEBUG_DFA}
+ { for optloop unit }
+ {$define DEBUG_OPTFORLOOP}
+ {$define DEBUG_OPTSTRENGTH}
+ { for optvirt unit }
+ {$define DEBUG_DEVIRT}
+{$endif}
+
{$define USEEXCEPT}
{$ifdef VER3_0}
diff --git a/avx512-0037785/compiler/globtype.pas b/avx512-0037785/compiler/globtype.pas
index 2e674ab459..c129d242b8 100644
--- a/avx512-0037785/compiler/globtype.pas
+++ b/avx512-0037785/compiler/globtype.pas
@@ -233,7 +233,9 @@ interface
cs_assemble_on_target,
{ use a memory model which allows large data structures, e.g. > 2 GB static data on x86-64 targets
this not supported on all OSes }
- cs_large
+ cs_large,
+ { if applicable, the compiler generates an executable in uf2 format }
+ cs_generate_uf2
);
tglobalswitches = set of tglobalswitch;
diff --git a/avx512-0037785/compiler/hlcgobj.pas b/avx512-0037785/compiler/hlcgobj.pas
index 12404fa07f..fd425ffc56 100644
--- a/avx512-0037785/compiler/hlcgobj.pas
+++ b/avx512-0037785/compiler/hlcgobj.pas
@@ -4901,6 +4901,7 @@ implementation
procedure thlcgobj.initialize_regvars(p: TObject; arg: pointer);
var
href : treference;
+ mmreg : tregister;
begin
if (tsym(p).typ=staticvarsym) and not(tstaticvarsym(p).noregvarinitneeded) then
begin
@@ -4922,12 +4923,18 @@ implementation
tstaticvarsym(p).initialloc.register);
end;
LOC_CMMREGISTER :
- { clear the whole register }
- a_opmm_reg_reg(TAsmList(arg),OP_XOR,tstaticvarsym(p).vardef,
- { as we pass shuffle=nil, we have to pass a full register }
- newreg(R_MMREGISTER,getsupreg(tstaticvarsym(p).initialloc.register),R_SUBMMWHOLE),
- newreg(R_MMREGISTER,getsupreg(tstaticvarsym(p).initialloc.register),R_SUBMMWHOLE),
- nil);
+ begin
+{$ifdef ARM}
+ { Do not pass d0 (which uses f0 and f1) for arm single type variable }
+ mmreg:=tstaticvarsym(p).initialloc.register;
+{$else}
+ { clear the whole register }
+ mmreg:=newreg(R_MMREGISTER,getsupreg(tstaticvarsym(p).initialloc.register),R_SUBMMWHOLE);
+{$endif}
+ a_opmm_reg_reg(TAsmList(arg),OP_XOR,tstaticvarsym(p).vardef, mmreg, mmreg,
+ { as we pass shuffle=nil, we have to pass a full register }
+ nil);
+ end;
LOC_CFPUREGISTER :
begin
{ initialize fpu regvar by loading from memory }
diff --git a/avx512-0037785/compiler/i386/aoptcpu.pas b/avx512-0037785/compiler/i386/aoptcpu.pas
index c6b667525e..fffa1a251d 100644
--- a/avx512-0037785/compiler/i386/aoptcpu.pas
+++ b/avx512-0037785/compiler/i386/aoptcpu.pas
@@ -137,6 +137,8 @@ unit aoptcpu;
if InsContainsSegRef(taicpu(p)) then
exit;
case taicpu(p).opcode Of
+ A_ADD:
+ Result:=OptPass1ADD(p);
A_AND:
Result:=OptPass1And(p);
A_IMUL:
diff --git a/avx512-0037785/compiler/i8086/cpupara.pas b/avx512-0037785/compiler/i8086/cpupara.pas
index db174e9ee4..628327db7e 100644
--- a/avx512-0037785/compiler/i8086/cpupara.pas
+++ b/avx512-0037785/compiler/i8086/cpupara.pas
@@ -101,8 +101,6 @@ unit cpupara;
function tcpuparamanager.ret_in_param(def:tdef;pd:tabstractprocdef):boolean;
- var
- size: longint;
begin
if handle_common_ret_in_param(def,pd,result) then
exit;
@@ -307,7 +305,6 @@ unit cpupara;
var
retcgsize : tcgsize;
paraloc : pcgparalocation;
- sym: tfieldvarsym;
usedef: tdef;
handled: boolean;
begin
diff --git a/avx512-0037785/compiler/i8086/n8086mem.pas b/avx512-0037785/compiler/i8086/n8086mem.pas
index 8e45c511e2..2a9de1fe6b 100644
--- a/avx512-0037785/compiler/i8086/n8086mem.pas
+++ b/avx512-0037785/compiler/i8086/n8086mem.pas
@@ -36,9 +36,9 @@ interface
protected
procedure set_labelsym_resultdef; override;
procedure set_absvarsym_resultdef; override;
- procedure pass_generate_code;override;
public
get_offset_only: boolean;
+ procedure pass_generate_code;override;
end;
ti8086derefnode = class(tx86derefnode)
diff --git a/avx512-0037785/compiler/i8086/n8086tcon.pas b/avx512-0037785/compiler/i8086/n8086tcon.pas
index e8f5ceb834..663a0806fc 100644
--- a/avx512-0037785/compiler/i8086/n8086tcon.pas
+++ b/avx512-0037785/compiler/i8086/n8086tcon.pas
@@ -57,7 +57,6 @@ uses
hp: tnode;
srsym: tsym;
pd: tprocdef;
- resourcestrrec: trecorddef;
begin
{ support word/smallint constants, initialized with Seg() }
if (def.ordtype in [u16bit,s16bit]) and (node.nodetype=inlinen) and
diff --git a/avx512-0037785/compiler/i8086/symcpu.pas b/avx512-0037785/compiler/i8086/symcpu.pas
index c614b8bc4a..c7d9ae05bd 100644
--- a/avx512-0037785/compiler/i8086/symcpu.pas
+++ b/avx512-0037785/compiler/i8086/symcpu.pas
@@ -130,6 +130,7 @@ type
- it has no 'near' or 'far' specifiers
- it is compiled in a $F- state }
function default_far:boolean;
+ protected
procedure Setinterfacedef(AValue: boolean);override;
public
constructor create(level:byte;doregister:boolean);override;
diff --git a/avx512-0037785/compiler/jvm/agjasmin.pas b/avx512-0037785/compiler/jvm/agjasmin.pas
index 58ed55ac42..1dde2ce7f9 100644
--- a/avx512-0037785/compiler/jvm/agjasmin.pas
+++ b/avx512-0037785/compiler/jvm/agjasmin.pas
@@ -1126,9 +1126,6 @@ implementation
function getopstr(const o:toper) : ansistring;
- var
- d: double;
- s: single;
begin
case o.typ of
top_reg:
diff --git a/avx512-0037785/compiler/jvm/cpubase.pas b/avx512-0037785/compiler/jvm/cpubase.pas
index d204cb6e92..5755bfda1b 100644
--- a/avx512-0037785/compiler/jvm/cpubase.pas
+++ b/avx512-0037785/compiler/jvm/cpubase.pas
@@ -302,11 +302,11 @@ uses
regnumber_index : array[tregisterindex] of tregisterindex = (
{$i rjvmrni.inc}
);
-
+(*
std_regname_index : array[tregisterindex] of tregisterindex = (
{$i rjvmsri.inc}
);
-
+*)
function reg_cgsize(const reg: tregister): tcgsize;
begin
result:=OS_NO;
diff --git a/avx512-0037785/compiler/jvm/dbgjasm.pas b/avx512-0037785/compiler/jvm/dbgjasm.pas
index 7186661093..fa475ec777 100644
--- a/avx512-0037785/compiler/jvm/dbgjasm.pas
+++ b/avx512-0037785/compiler/jvm/dbgjasm.pas
@@ -105,7 +105,6 @@ implementation
afterprocstartlabel : tasmlabel;
hp,
afterproccodestart : tai;
- instrcount : longint;
begin
{ insert debug information for local variables and parameters, but only
for routines implemented in the Pascal code }
@@ -121,7 +120,6 @@ implementation
{ set the start label for local variables after the first instruction,
because javac's code completion support assumes that all info at
bytecode position 0 is for parameters }
- instrcount:=0;
afterproccodestart:=def.procstarttai;
while assigned(afterproccodestart.next) do
begin
diff --git a/avx512-0037785/compiler/jvm/hlcgcpu.pas b/avx512-0037785/compiler/jvm/hlcgcpu.pas
index b9f4f5f8b1..7bf73b2e04 100644
--- a/avx512-0037785/compiler/jvm/hlcgcpu.pas
+++ b/avx512-0037785/compiler/jvm/hlcgcpu.pas
@@ -188,6 +188,8 @@ uses
procedure gen_initialize_fields_code(list:TAsmList);
procedure gen_typecheck(list: TAsmList; checkop: tasmop; checkdef: tdef);
+
+ procedure g_copyvalueparas(p: TObject; arg: pointer); override;
protected
procedure a_load_const_stack_intern(list : TAsmList;size : tdef;a : tcgint; typ: TRegisterType; legalize_const: boolean);
@@ -198,8 +200,6 @@ uses
procedure allocate_implicit_struct_with_base_ref(list: TAsmList; vs: tabstractvarsym; ref: treference);
procedure gen_load_uninitialized_function_result(list: TAsmList; pd: tprocdef; resdef: tdef; const resloc: tcgpara); override;
- procedure g_copyvalueparas(p: TObject; arg: pointer); override;
-
procedure inittempvariables(list:TAsmList);override;
function g_call_system_proc_intern(list: TAsmList; pd: tprocdef; const paras: array of pcgpara; forceresdef: tdef): tcgpara; override;
diff --git a/avx512-0037785/compiler/jvm/njvminl.pas b/avx512-0037785/compiler/jvm/njvminl.pas
index 34af3952a8..f1a9358f38 100644
--- a/avx512-0037785/compiler/jvm/njvminl.pas
+++ b/avx512-0037785/compiler/jvm/njvminl.pas
@@ -161,7 +161,7 @@ implementation
function tjvminlinenode.first_copy: tnode;
var
ppn: tcallparanode;
- arr, len, start, kind: tnode;
+ arr, len, start: tnode;
eledef: tdef;
counter, ndims: longint;
finaltype: char;
@@ -401,7 +401,6 @@ implementation
lefttemp: ttempcreatenode;
newblock: tblocknode;
newstatement: tstatementnode;
- primitive: boolean;
begin
{ first parameter is the array, the rest are the dimensions }
newparas:=tcallparanode(left).right;
diff --git a/avx512-0037785/compiler/jvm/njvmmat.pas b/avx512-0037785/compiler/jvm/njvmmat.pas
index 61fb0bf586..0e473bdfde 100644
--- a/avx512-0037785/compiler/jvm/njvmmat.pas
+++ b/avx512-0037785/compiler/jvm/njvmmat.pas
@@ -78,7 +78,6 @@ implementation
var
tmpreg: tregister;
lab: tasmlabel;
- ovloc: tlocation;
op: topcg;
isu32int: boolean;
begin
diff --git a/avx512-0037785/compiler/jvm/njvmmem.pas b/avx512-0037785/compiler/jvm/njvmmem.pas
index 9c608746f6..d51d3b1d42 100644
--- a/avx512-0037785/compiler/jvm/njvmmem.pas
+++ b/avx512-0037785/compiler/jvm/njvmmem.pas
@@ -179,10 +179,7 @@ implementation
function tjvmaddrnode.isdererence: boolean;
- var
- target: tnode;
begin
- target:=actualtargetnode(@left)^;
result:=
(left.nodetype=derefn);
end;
diff --git a/avx512-0037785/compiler/m68k/aoptcpu.pas b/avx512-0037785/compiler/m68k/aoptcpu.pas
index 948bc28ff1..79b4331895 100644
--- a/avx512-0037785/compiler/m68k/aoptcpu.pas
+++ b/avx512-0037785/compiler/m68k/aoptcpu.pas
@@ -253,26 +253,30 @@ unit aoptcpu;
opstr:=opname(p);
case taicpu(p).oper[0]^.typ of
top_reg:
- begin
- { move %reg0, %tmpreg; move %tmpreg, <ea> -> move %reg0, <ea> }
- taicpu(p).loadOper(1,taicpu(next).oper[1]^);
- asml.remove(next);
- next.free;
- result:=true;
- { also remove leftover move %reg0, %reg0, which can occur as the result
- of the previous optimization, if %reg0 and %tmpreg was different types
- (addr vs. data), so these moves were left in by the cg }
- if MatchOperand(taicpu(p).oper[0]^,taicpu(p).oper[1]^) then
- begin
- DebugMsg('Optimizer: '+opstr+' + '+opstr+' removed',p);
- GetNextInstruction(p,next);
- asml.remove(p);
- p.free;
- p:=next;
- end
- else
- DebugMsg('Optimizer: '+opstr+' + '+opstr+' to '+opstr+' #1',p)
- end;
+ { do not optimize away FPU to INT to FPU reg moves. These are used for
+ to-single-rounding on FPUs which have no FSMOVE/FDMOVE. (KB) }
+ if not ((taicpu(p).opcode = A_FMOVE) and
+ (getregtype(taicpu(p).oper[0]^.reg) <> getregtype(taicpu(p).oper[1]^.reg))) then
+ begin
+ { move %reg0, %tmpreg; move %tmpreg, <ea> -> move %reg0, <ea> }
+ taicpu(p).loadOper(1,taicpu(next).oper[1]^);
+ asml.remove(next);
+ next.free;
+ result:=true;
+ { also remove leftover move %reg0, %reg0, which can occur as the result
+ of the previous optimization, if %reg0 and %tmpreg was different types
+ (addr vs. data), so these moves were left in by the cg }
+ if MatchOperand(taicpu(p).oper[0]^,taicpu(p).oper[1]^) then
+ begin
+ DebugMsg('Optimizer: '+opstr+' + '+opstr+' removed',p);
+ GetNextInstruction(p,next);
+ asml.remove(p);
+ p.free;
+ p:=next;
+ end
+ else
+ DebugMsg('Optimizer: '+opstr+' + '+opstr+' to '+opstr+' #1',p)
+ end;
top_const:
begin
// DebugMsg('Optimizer: '+opstr+' + '+opstr+' to '+opstr+' #2',p);
diff --git a/avx512-0037785/compiler/m68k/cgcpu.pas b/avx512-0037785/compiler/m68k/cgcpu.pas
index d46b5c4f07..be88900d21 100644
--- a/avx512-0037785/compiler/m68k/cgcpu.pas
+++ b/avx512-0037785/compiler/m68k/cgcpu.pas
@@ -1051,10 +1051,40 @@ unit cgcpu;
procedure tcg68k.a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister);
var
instr : taicpu;
+ op: tasmop;
+ href: treference;
+ hreg: tregister;
begin
- instr:=taicpu.op_reg_reg(A_FMOVE,fpuregopsize,reg1,reg2);
- add_move_instruction(instr);
- list.concat(instr);
+ if fromsize > tosize then
+ begin
+ { we have to do a load-store through an intregister or the stack in this case,
+ which is probably the fastest way, and simpler than messing around with FPU control
+ words for one-off custom rounding (KB) }
+ case tosize of
+ OS_F32:
+ begin
+ //list.concat(tai_comment.create(strpnew('a_loadfpu_reg_reg rounding via intreg')));
+ hreg := getintregister(list,OS_32);
+ list.concat(taicpu.op_reg_reg(A_FMOVE, tcgsize2opsize[tosize], reg1, hreg));
+ list.concat(taicpu.op_reg_reg(A_FMOVE, tcgsize2opsize[tosize], hreg, reg2));
+ end;
+ else
+ begin
+ //list.concat(tai_comment.create(strpnew('a_loadfpu_reg_reg rounding via stack')));
+ reference_reset_base(href, NR_STACK_POINTER_REG, 0, ctempposinvalid, 0, []);
+ href.direction:=dir_dec;
+ list.concat(taicpu.op_reg_ref(A_FMOVE, tcgsize2opsize[tosize], reg1, href));
+ href.direction:=dir_inc;
+ list.concat(taicpu.op_ref_reg(A_FMOVE, tcgsize2opsize[tosize], href, reg2));
+ end;
+ end;
+ end
+ else
+ begin
+ instr:=taicpu.op_reg_reg(A_FMOVE,fpuregopsize,reg1,reg2);
+ add_move_instruction(instr);
+ list.concat(instr);
+ end;
end;
@@ -1067,6 +1097,8 @@ unit cgcpu;
href := ref;
fixref(list,href,current_settings.fputype = fpu_coldfire);
list.concat(taicpu.op_ref_reg(A_FMOVE,opsize,href,reg));
+ if fromsize > tosize then
+ a_load_reg_reg(list,fromsize,tosize,reg,reg);
end;
procedure tcg68k.a_loadfpu_reg_ref(list: TAsmList; fromsize,tosize: tcgsize; reg: tregister; const ref: treference);
diff --git a/avx512-0037785/compiler/msg/errorct.msg b/avx512-0037785/compiler/msg/errorct.msg
index 3aea8fafb2..1275367752 100644
--- a/avx512-0037785/compiler/msg/errorct.msg
+++ b/avx512-0037785/compiler/msg/errorct.msg
@@ -1,6 +1,6 @@
#
# This file is part of the Free Pascal Compiler
-# Copyright (c) 1993-2020 by the Free Pascal Development team
+# Copyright (c) 1993-2021 by the Free Pascal Development team
#
# Catalan Language File for Free Pascal
#
@@ -2103,7 +2103,7 @@ option_code_page_not_available=11039_E_La pgina del codi no est disponible
#
option_logo=11023_[
Free Pascal Compiler versi $FPCFULLVERSION [$FPCDATE] per $FPCCPU
-Copyright (c) 1993-2020 per Florian Klaempfl and others
+Copyright (c) 1993-2021 per Florian Klaempfl and others
]
#
diff --git a/avx512-0037785/compiler/msg/errord.msg b/avx512-0037785/compiler/msg/errord.msg
index 59e7afc577..d8e37df549 100644
--- a/avx512-0037785/compiler/msg/errord.msg
+++ b/avx512-0037785/compiler/msg/errord.msg
@@ -6,7 +6,7 @@
# Based on errore.msg of SVN revision 45316
#
# This file is part of the Free Pascal Compiler
-# Copyright (c) 1998-2020 by the Free Pascal Development team
+# Copyright (c) 1998-2021 by the Free Pascal Development team
#
# See the file COPYING.v2, included in this distribution,
# for details about the copyright.
@@ -3585,7 +3585,7 @@ option_invalid_iphoneos_deployment_target=11051_E_Ungltiger Wert fr die Umgebu
% XY.Z or XY.Z.AB with X, Y,Z , A and B all digits from 0-9.
% In case of iOS, it has to be X.Z.A, where X, Z and A can all be either 1 or 2
% digits from 0-9.
-option_illegal_fpu_eabihf=11052_E_Sie mssen beim Ziel EABIHF ABI einen der FPU Typen VFPV2, VFPV3 oder VFPV3_D16 verwenden
+option_illegal_fpu_eabihf=11052_E_Sie mssen beim Ziel EABIHF ABI einen der VFP FPU-Typen verwenden
% The EABIHF (VFP hardfloat) ABI target can only be used with VFP FPUs.
option_w_unsupported_debug_format=11053_W_Das ausgewhlte Debugformat wird auf dem aktuellen Ziel nicht untersttzt. Die aktuelle Einstellung wird beibehalten
% Not all targets support all debug formats (in particular, Stabs is not supported on 64 bit targets).
@@ -3784,7 +3784,7 @@ package_u_ppl_filename=13029_U_PPL Dateiname $1
#
option_logo=11023_[
Free Pascal Compiler Version $FPCFULLVERSION [$FPCDATE] fr $FPCTARGET
-Copyright (c) 1993-2020 Florian Klmpfl und andere
+Copyright (c) 1993-2021 Florian Klmpfl und andere
]
#
diff --git a/avx512-0037785/compiler/msg/errorda.msg b/avx512-0037785/compiler/msg/errorda.msg
index b4b0ab21f2..f610f8fabf 100644
--- a/avx512-0037785/compiler/msg/errorda.msg
+++ b/avx512-0037785/compiler/msg/errorda.msg
@@ -3438,7 +3438,7 @@ option_invalid_iphoneos_deployment_target=11051_E_Invalid value for IPHONEOS_DEP
% XY.Z or XY.Z.AB with X, Y,Z , A and B all digits from 0-9.
% In case of iOS, it has to be X.Z.A, where X, Z and A can all be either 1 or 2
% digits from 0-9.
-option_illegal_fpu_eabihf=11052_E_You must use a FPU type of VFPV2, VFPV3 or VFPV3_D16 when using the EABIHF ABI target
+option_illegal_fpu_eabihf=11052_E_You must use one of the VFP FPU types when using the EABIHF ABI target
% The EABIHF (VFP hardfloat) ABI target can only be used with VFP FPUs.
option_w_unsupported_debug_format=11053_W_The selected debug format is not supported on the current target, not changing the current setting
% Not all targets support all debug formats (in particular, Stabs is not supported on 64 bit targets).
@@ -3535,7 +3535,7 @@ wpo_cant_create_feedback_file=12019_E_Cannot create specified whole program opti
#
option_logo=11023_[
Free Pascal Compiler version $FPCFULLVERSION [$FPCDATE] til $FPCTARGET
-Copyright (c) 1993-2020 Florian Klaempfl and others
+Copyright (c) 1993-2021 Florian Klaempfl and others
]
#
diff --git a/avx512-0037785/compiler/msg/errordu.msg b/avx512-0037785/compiler/msg/errordu.msg
index e03e4ea1ec..7a02a6d617 100644
--- a/avx512-0037785/compiler/msg/errordu.msg
+++ b/avx512-0037785/compiler/msg/errordu.msg
@@ -6,7 +6,7 @@
# Based on errore.msg of SVN revision 45316
#
# This file is part of the Free Pascal Compiler
-# Copyright (c) 1998-2020 by the Free Pascal Development team
+# Copyright (c) 1998-2021 by the Free Pascal Development team
#
# See the file COPYING.v2, included in this distribution,
# for details about the copyright.
@@ -3585,7 +3585,7 @@ option_invalid_iphoneos_deployment_target=11051_E_Ungültiger Wert für die Umge
% XY.Z or XY.Z.AB with X, Y,Z , A and B all digits from 0-9.
% In case of iOS, it has to be X.Z.A, where X, Z and A can all be either 1 or 2
% digits from 0-9.
-option_illegal_fpu_eabihf=11052_E_Sie müssen beim Ziel EABIHF ABI einen der FPU Typen VFPV2, VFPV3 oder VFPV3_D16 verwenden
+option_illegal_fpu_eabihf=11052_E_Sie müssen beim Ziel EABIHF ABI einen der VFP FPU-Typen verwenden
% The EABIHF (VFP hardfloat) ABI target can only be used with VFP FPUs.
option_w_unsupported_debug_format=11053_W_Das ausgewählte Debugformat wird auf dem aktuellen Ziel nicht unterstützt. Die aktuelle Einstellung wird beibehalten
% Not all targets support all debug formats (in particular, Stabs is not supported on 64 bit targets).
@@ -3784,7 +3784,7 @@ package_u_ppl_filename=13029_U_PPL Dateiname $1
#
option_logo=11023_[
Free Pascal Compiler Version $FPCFULLVERSION [$FPCDATE] für $FPCTARGET
-Copyright (c) 1993-2020 Florian Klämpfl und andere
+Copyright (c) 1993-2021 Florian Klämpfl und andere
]
#
diff --git a/avx512-0037785/compiler/msg/errore.msg b/avx512-0037785/compiler/msg/errore.msg
index 9874f1e40c..78d0f1bf78 100644
--- a/avx512-0037785/compiler/msg/errore.msg
+++ b/avx512-0037785/compiler/msg/errore.msg
@@ -1555,7 +1555,7 @@ parser_w_ptr_type_ignored=03338_W_Pointer type "$1" ignored
% The specified pointer type modifier is ignored, because it is not supported on
% the current platform. This happens, for example, when a far pointer is
% declared on a non-x86 platform.
-parser_e_global_generic_references_static=03339_E_Global Generic template references static symtable
+parser_e_global_generic_references_static=03339_E_Generic template in interface section references symbol in implementation section
% A generic declared in the interface section of a unit must not reference symbols that belong
% solely to the implementation section of that unit.
parser_u_already_compiled=03340_UL_Unit $1 has been already compiled meanwhile.
@@ -1622,6 +1622,8 @@ parser_e_location_regpair_only_data=03358_E_Only data registers are supported fo
% AmigaOS/MorphOS syscall specific: for 64bit register pairs, only data registers are supported
parser_e_location_regpair_only_consecutive=03359_E_Only consecutive registers are supported for explicit location register pairs
% MorphOS syscall specific: only consecutive (f.e.: d1-d2) registers are supported for 64bit register pairs
+parser_e_constructurs_cannot_take_type_parameters=03360_E_Constructors cannot take type parameters
+% The use of type parameters in constructors is not allowed.
%
% \end{description}
%
@@ -3556,7 +3558,7 @@ option_invalid_iphoneos_deployment_target=11051_E_Invalid value for IPHONEOS_DEP
% XY.Z or XY.Z.AB with X, Y,Z , A and B all digits from 0-9.
% In case of iOS, it has to be X.Z.A, where X, Z and A can all be either 1 or 2
% digits from 0-9.
-option_illegal_fpu_eabihf=11052_E_You must use a FPU type of VFPV2, VFPV3 or VFPV3_D16 when using the EABIHF ABI target
+option_illegal_fpu_eabihf=11052_E_You must use one of the VFP FPU types when using the EABIHF ABI target
% The EABIHF (VFP hardfloat) ABI target can only be used with VFP FPUs.
option_w_unsupported_debug_format=11053_W_The selected debug format is not supported on the current target, not changing the current setting
% Not all targets support all debug formats (in particular, Stabs is not supported on 64 bit targets).
@@ -3755,7 +3757,7 @@ package_u_ppl_filename=13029_U_PPL filename $1
#
option_logo=11023_[
Free Pascal Compiler version $FPCFULLVERSION [$FPCDATE] for $FPCCPU
-Copyright (c) 1993-2020 by Florian Klaempfl and others
+Copyright (c) 1993-2021 by Florian Klaempfl and others
]
#
@@ -4348,6 +4350,7 @@ F*2Xp<x>_First search for the compiler binary in the directory <x>
**2Xs_Strip all symbols from executable
**2XS_Try to link units statically (default, defines FPC_LINK_STATIC)
**2Xt_Link with static libraries (-static is passed to linker)
+**2Xu_Generate executable in UF2 format (embedded targets only)
**2Xv_Generate table for Virtual Entry calls
**2XV_Use VLink as external linker (default on Amiga, MorphOS)
**2XX_Try to smartlink units (defines FPC_LINK_SMART)
diff --git a/avx512-0037785/compiler/msg/errores.msg b/avx512-0037785/compiler/msg/errores.msg
index 93e86399f3..e7eff83ce7 100644
--- a/avx512-0037785/compiler/msg/errores.msg
+++ b/avx512-0037785/compiler/msg/errores.msg
@@ -3380,7 +3380,7 @@ option_invalid_iphoneos_deployment_target=11051_E_Invalid value for IPHONEOS_DEP
% XY.Z or XY.Z.AB with X, Y,Z , A and B all digits from 0-9.
% In case of iOS, it has to be X.Z.A, where X, Z and A can all be either 1 or 2
% digits from 0-9.
-option_illegal_fpu_eabihf=11052_E_You must use a FPU type of VFPV2, VFPV3 or VFPV3_D16 when using the EABIHF ABI target
+option_illegal_fpu_eabihf=11052_E_You must use one of the VFP FPU types when using the EABIHF ABI target
% The EABIHF (VFP hardfloat) ABI target can only be used with VFP FPUs.
option_w_unsupported_debug_format=11053_W_The selected debug format is not supported on the current target, not changing the current setting
% Not all targets support all debug formats (in particular, Stabs is not supported on 64 bit targets).
@@ -3477,7 +3477,7 @@ wpo_cant_create_feedback_file=12019_E_Cannot create specified whole program opti
#
option_logo=11023_[
Free Pascal Compiler version $FPCFULLVERSION [$FPCDATE] for $FPCCPU
-Copyright (c) 1993-2020 by Florian Klaempfl and others
+Copyright (c) 1993-2021 by Florian Klaempfl and others
]
#
diff --git a/avx512-0037785/compiler/msg/errorf.msg b/avx512-0037785/compiler/msg/errorf.msg
index 1174238b5d..3ca9d2f308 100644
--- a/avx512-0037785/compiler/msg/errorf.msg
+++ b/avx512-0037785/compiler/msg/errorf.msg
@@ -1715,7 +1715,7 @@ option_asm_forced=11022_W_"$1" assembler use forced
#
option_logo=11023_[
Compilateur Free Pascal version $FPCFULLVERSION [$FPCDATE] pour $FPCTARGET
-Copyright (c) 1993-2020 by Florian Klaempfl and others
+Copyright (c) 1993-2021 by Florian Klaempfl and others
]
#
diff --git a/avx512-0037785/compiler/msg/errorfi.msg b/avx512-0037785/compiler/msg/errorfi.msg
index 1dadd321c4..a1c91eadc2 100644
--- a/avx512-0037785/compiler/msg/errorfi.msg
+++ b/avx512-0037785/compiler/msg/errorfi.msg
@@ -3403,7 +3403,7 @@ option_invalid_iphoneos_deployment_target=11051_E_Invalid value for IPHONEOS_DEP
% XY.Z or XY.Z.AB with X, Y,Z , A and B all digits from 0-9.
% In case of iOS, it has to be X.Z.A, where X, Z and A can all be either 1 or 2
% digits from 0-9.
-option_illegal_fpu_eabihf=11052_E_You must use a FPU type of VFPV2, VFPV3 or VFPV3_D16 when using the EABIHF ABI target
+option_illegal_fpu_eabihf=11052_E_You must use one of the VFP FPU types when using the EABIHF ABI target
% The EABIHF (VFP hardfloat) ABI target can only be used with VFP FPUs.
option_w_unsupported_debug_format=11053_W_The selected debug format is not supported on the current target, not changing the current setting
% Not all targets support all debug formats (in particular, Stabs is not supported on 64 bit targets).
@@ -3499,7 +3499,7 @@ wpo_cant_create_feedback_file=12019_E_Cannot create specified whole program opti
# Logo (option -l)
#
option_logo=11023_[ Compilateur Free Pascal version $FPCFULLVERSION [$FPCDATE] for $FPCCPU
-Copyright (c) 1993-2020, Florian Klaempfl and others]
+Copyright (c) 1993-2021, Florian Klaempfl and others]
#
# Info (option -i)
#
diff --git a/avx512-0037785/compiler/msg/errorhe.msg b/avx512-0037785/compiler/msg/errorhe.msg
index 524621bfd8..b9ef626478 100644
--- a/avx512-0037785/compiler/msg/errorhe.msg
+++ b/avx512-0037785/compiler/msg/errorhe.msg
@@ -2407,7 +2407,7 @@ option_confict_asm_debug=11041_W_ "$1"
#
option_logo=11023_[
Free Pascal Compiler version $FPCFULLVERSION [$FPCDATE] for $FPCCPU
-Copyright (c) 1993-2020 by Florian Klaempfl and others
+Copyright (c) 1993-2021 by Florian Klaempfl and others
]
#
diff --git a/avx512-0037785/compiler/msg/errorheu.msg b/avx512-0037785/compiler/msg/errorheu.msg
index 04b2db1fac..a9548f08fa 100644
--- a/avx512-0037785/compiler/msg/errorheu.msg
+++ b/avx512-0037785/compiler/msg/errorheu.msg
@@ -3399,7 +3399,7 @@ option_invalid_iphoneos_deployment_target=11051_E_Invalid value for IPHONEOS_DEP
% XY.Z or XY.Z.AB with X, Y,Z , A and B all digits from 0-9.
% In case of iOS, it has to be X.Z.A, where X, Z and A can all be either 1 or 2
% digits from 0-9.
-option_illegal_fpu_eabihf=11052_E_You must use a FPU type of VFPV2, VFPV3 or VFPV3_D16 when using the EABIHF ABI target
+option_illegal_fpu_eabihf=11052_E_You must use one of the VFP FPU types when using the EABIHF ABI target
% The EABIHF (VFP hardfloat) ABI target can only be used with VFP FPUs.
option_w_unsupported_debug_format=11053_W_The selected debug format is not supported on the current target, not changing the current setting
% Not all targets support all debug formats (in particular, Stabs is not supported on 64 bit targets).
@@ -3496,7 +3496,7 @@ wpo_cant_create_feedback_file=12019_E_Cannot create specified whole program opti
#
option_logo=11023_[
Free Pascal Compiler version $FPCFULLVERSION [$FPCDATE] for $FPCCPU
-Copyright (c) 1993-2020 by Florian Klaempfl and others
+Copyright (c) 1993-2021 by Florian Klaempfl and others
]
#
diff --git a/avx512-0037785/compiler/msg/errorid.msg b/avx512-0037785/compiler/msg/errorid.msg
index a0f29b8484..9c6d0ecda7 100644
--- a/avx512-0037785/compiler/msg/errorid.msg
+++ b/avx512-0037785/compiler/msg/errorid.msg
@@ -3407,7 +3407,7 @@ option_invalid_iphoneos_deployment_target=11051_E_Invalid value for IPHONEOS_DEP
% XY.Z or XY.Z.AB with X, Y,Z , A and B all digits from 0-9.
% In case of iOS, it has to be X.Z.A, where X, Z and A can all be either 1 or 2
% digits from 0-9.
-option_illegal_fpu_eabihf=11052_E_You must use a FPU type of VFPV2, VFPV3 or VFPV3_D16 when using the EABIHF ABI target
+option_illegal_fpu_eabihf=11052_E_You must use one of the VFP FPU types when using the EABIHF ABI target
% The EABIHF (VFP hardfloat) ABI target can only be used with VFP FPUs.
option_w_unsupported_debug_format=11053_W_The selected debug format is not supported on the current target, not changing the current setting
% Not all targets support all debug formats (in particular, Stabs is not supported on 64 bit targets).
@@ -3504,7 +3504,7 @@ wpo_cant_create_feedback_file=12019_E_Cannot create specified whole program opti
#
option_logo=11023_[
Free Pascal Compiler versi $FPCFULLVERSION [$FPCDATE] untuk $FPCCPU
-Hak Cipta (c) 1993-2020 oleh Florian Klaempfl and others
+Hak Cipta (c) 1993-2021 oleh Florian Klaempfl and others
]
#
diff --git a/avx512-0037785/compiler/msg/erroriu.msg b/avx512-0037785/compiler/msg/erroriu.msg
index 22c8be009e..127634d57d 100644
--- a/avx512-0037785/compiler/msg/erroriu.msg
+++ b/avx512-0037785/compiler/msg/erroriu.msg
@@ -2693,7 +2693,7 @@ wpo_cant_create_feedback_file=12019_E_Impossibile creare il file di feedback "$1
#
option_logo=11023_[
Compilatore Free Pascal, versione $FPCFULLVERSION [$FPCDATE] per $FPCCPU
-Copyright (c) 1993-2020 di Florian Klaempfl and others
+Copyright (c) 1993-2021 di Florian Klaempfl and others
]
#
diff --git a/avx512-0037785/compiler/msg/errorn.msg b/avx512-0037785/compiler/msg/errorn.msg
index 4f7fc19e20..25140d19b4 100644
--- a/avx512-0037785/compiler/msg/errorn.msg
+++ b/avx512-0037785/compiler/msg/errorn.msg
@@ -3388,7 +3388,7 @@ option_invalid_iphoneos_deployment_target=11051_E_Invalid value for IPHONEOS_DEP
% XY.Z or XY.Z.AB with X, Y,Z , A and B all digits from 0-9.
% In case of iOS, it has to be X.Z.A, where X, Z and A can all be either 1 or 2
% digits from 0-9.
-option_illegal_fpu_eabihf=11052_E_You must use a FPU type of VFPV2, VFPV3 or VFPV3_D16 when using the EABIHF ABI target
+option_illegal_fpu_eabihf=11052_E_You must use one of the VFP FPU types when using the EABIHF ABI target
% The EABIHF (VFP hardfloat) ABI target can only be used with VFP FPUs.
option_w_unsupported_debug_format=11053_W_The selected debug format is not supported on the current target, not changing the current setting
% Not all targets support all debug formats (in particular, Stabs is not supported on 64 bit targets).
@@ -3485,7 +3485,7 @@ wpo_cant_create_feedback_file=12019_E_Cannot create specified whole program opti
#
option_logo=11023_[
Free Pascal Compiler versie $FPCFULLVERSION [$FPCDATE] voor $FPCTARGET
-Copyright (c) 1993-2020 door Florian Klaempfl en anderen
+Copyright (c) 1993-2021 door Florian Klaempfl en anderen
]
#
# Info (option -i)
diff --git a/avx512-0037785/compiler/msg/errorpl.msg b/avx512-0037785/compiler/msg/errorpl.msg
index 6db59ac21e..5270079c39 100644
--- a/avx512-0037785/compiler/msg/errorpl.msg
+++ b/avx512-0037785/compiler/msg/errorpl.msg
@@ -2119,7 +2119,7 @@ option_code_page_not_available=11039_E_Nieznana strona kodowa
#
option_logo=11023_[
Free Pascal Compiler wersja $FPCFULLVERSION [$FPCDATE] dla $FPCCPU
-Copyright (c) 1993-2020 by Florian Klaempfl and others
+Copyright (c) 1993-2021 by Florian Klaempfl and others
]
#
diff --git a/avx512-0037785/compiler/msg/errorpli.msg b/avx512-0037785/compiler/msg/errorpli.msg
index fad211bef8..a306a6f1b8 100644
--- a/avx512-0037785/compiler/msg/errorpli.msg
+++ b/avx512-0037785/compiler/msg/errorpli.msg
@@ -2119,7 +2119,7 @@ option_code_page_not_available=11039_E_Nieznana strona kodowa
#
option_logo=11023_[
Free Pascal Compiler wersja $FPCFULLVERSION [$FPCDATE] dla $FPCCPU
-Copyright (c) 1993-2020 by Florian Klaempfl and others
+Copyright (c) 1993-2021 by Florian Klaempfl and others
]
#
diff --git a/avx512-0037785/compiler/msg/errorpt.msg b/avx512-0037785/compiler/msg/errorpt.msg
index 8703d4fd8e..e01dfef32b 100644
--- a/avx512-0037785/compiler/msg/errorpt.msg
+++ b/avx512-0037785/compiler/msg/errorpt.msg
@@ -3086,7 +3086,7 @@ wpo_cant_create_feedback_file=12019_E_Impossvel criar arquivo retorno otimiza
#
option_logo=11023_[
Compilador Free Pascal verso $FPCFULLVERSION [$FPCDATE] para $FPCCPU
-Copyright (c) 1993-2020 by Florian Klaempfl and others
+Copyright (c) 1993-2021 by Florian Klaempfl and others
]
#
diff --git a/avx512-0037785/compiler/msg/errorptu.msg b/avx512-0037785/compiler/msg/errorptu.msg
index 6ae762e814..4bbed9672c 100644
--- a/avx512-0037785/compiler/msg/errorptu.msg
+++ b/avx512-0037785/compiler/msg/errorptu.msg
@@ -3417,7 +3417,7 @@ option_invalid_iphoneos_deployment_target=11051_E_Invalid value for IPHONEOS_DEP
% XY.Z or XY.Z.AB with X, Y,Z , A and B all digits from 0-9.
% In case of iOS, it has to be X.Z.A, where X, Z and A can all be either 1 or 2
% digits from 0-9.
-option_illegal_fpu_eabihf=11052_E_You must use a FPU type of VFPV2, VFPV3 or VFPV3_D16 when using the EABIHF ABI target
+option_illegal_fpu_eabihf=11052_E_You must use one of the VFP FPU types when using the EABIHF ABI target
% The EABIHF (VFP hardfloat) ABI target can only be used with VFP FPUs.
option_w_unsupported_debug_format=11053_W_The selected debug format is not supported on the current target, not changing the current setting
% Not all targets support all debug formats (in particular, Stabs is not supported on 64 bit targets).
@@ -3514,7 +3514,7 @@ wpo_cant_create_feedback_file=12019_E_Impossível criar arquivo retorno otimiza
#
option_logo=11023_[
Compilador Free Pascal versão $FPCFULLVERSION [$FPCDATE] para $FPCCPU
-Copyright (c) 1993-2020 by Florian Klaempfl and others
+Copyright (c) 1993-2021 by Florian Klaempfl and others
]
#
diff --git a/avx512-0037785/compiler/msg/errorr.msg b/avx512-0037785/compiler/msg/errorr.msg
index de376fdde6..b34a0342fe 100644
--- a/avx512-0037785/compiler/msg/errorr.msg
+++ b/avx512-0037785/compiler/msg/errorr.msg
@@ -2506,7 +2506,7 @@ wpo_cant_create_feedback_file=12019_E_ ᮧ 䠩 ⭮ 裡 "$1"
#
option_logo=11023_[
Free Pascal ᨨ $FPCFULLVERSION [$FPCDATE] $FPCCPU
-Copyright (c) 1993-2020 by Florian Klaempfl and others
+Copyright (c) 1993-2021 by Florian Klaempfl and others
]
#
diff --git a/avx512-0037785/compiler/msg/errorru.msg b/avx512-0037785/compiler/msg/errorru.msg
index 1f39e64e7b..77be2cfe0c 100644
--- a/avx512-0037785/compiler/msg/errorru.msg
+++ b/avx512-0037785/compiler/msg/errorru.msg
@@ -3292,7 +3292,7 @@ option_invalid_iphoneos_deployment_target=11051_E_Invalid value for IPHONEOS_DEP
% XY.Z or XY.Z.AB with X, Y,Z , A and B all digits from 0-9.
% In case of iOS, it has to be X.Z.A, where X, Z and A can all be either 1 or 2
% digits from 0-9.
-option_illegal_fpu_eabihf=11052_E_You must use a FPU type of VFPV2, VFPV3 or VFPV3_D16 when using the EABIHF ABI target
+option_illegal_fpu_eabihf=11052_E_You must use one of the VFP FPU types when using the EABIHF ABI target
% The EABIHF (VFP hardfloat) ABI target can only be used with VFP FPUs.
option_w_unsupported_debug_format=11053_W_The selected debug format is not supported on the current target, not changing the current setting
% Not all targets support all debug formats (in particular, Stabs is not supported on 64 bit targets).
@@ -3387,7 +3387,7 @@ wpo_cant_create_feedback_file=12019_E_Невозможно создать фай
#
option_logo=11023_[
Компилятор Free Pascal версии $FPCFULLVERSION [$FPCDATE] для $FPCCPU
-Copyright (c) 1993-2020 by Florian Klaempfl and others
+Copyright (c) 1993-2021 by Florian Klaempfl and others
]
#
diff --git a/avx512-0037785/compiler/msg/errorues.msg b/avx512-0037785/compiler/msg/errorues.msg
index 5777a05d13..2398ea14dd 100644
--- a/avx512-0037785/compiler/msg/errorues.msg
+++ b/avx512-0037785/compiler/msg/errorues.msg
@@ -3374,7 +3374,7 @@ option_invalid_iphoneos_deployment_target=11051_E_Invalid value for IPHONEOS_DEP
% XY.Z or XY.Z.AB with X, Y,Z , A and B all digits from 0-9.
% In case of iOS, it has to be X.Z.A, where X, Z and A can all be either 1 or 2
% digits from 0-9.
-option_illegal_fpu_eabihf=11052_E_You must use a FPU type of VFPV2, VFPV3 or VFPV3_D16 when using the EABIHF ABI target
+option_illegal_fpu_eabihf=11052_E_You must use one of the VFP FPU types when using the EABIHF ABI target
% The EABIHF (VFP hardfloat) ABI target can only be used with VFP FPUs.
option_w_unsupported_debug_format=11053_W_The selected debug format is not supported on the current target, not changing the current setting
% Not all targets support all debug formats (in particular, Stabs is not supported on 64 bit targets).
@@ -3471,7 +3471,7 @@ wpo_cant_create_feedback_file=12019_E_Cannot create specified whole program opti
#
option_logo=11023_[
Free Pascal Compiler version $FPCFULLVERSION [$FPCDATE] for $FPCCPU
-Copyright (c) 1993-2020 by Florian Klaempfl and others
+Copyright (c) 1993-2021 by Florian Klaempfl and others
]
#
diff --git a/avx512-0037785/compiler/msgidx.inc b/avx512-0037785/compiler/msgidx.inc
index e7232b2c39..dd0f203213 100644
--- a/avx512-0037785/compiler/msgidx.inc
+++ b/avx512-0037785/compiler/msgidx.inc
@@ -471,6 +471,7 @@ const
parser_e_location_size_too_large=03357;
parser_e_location_regpair_only_data=03358;
parser_e_location_regpair_only_consecutive=03359;
+ parser_e_constructurs_cannot_take_type_parameters=03360;
type_e_mismatch=04000;
type_e_incompatible_types=04001;
type_e_not_equal_types=04002;
@@ -1136,9 +1137,9 @@ const
option_info=11024;
option_help_pages=11025;
- MsgTxtSize = 86940;
+ MsgTxtSize = 87070;
MsgIdxMax : array[1..20] of longint=(
- 28,107,360,130,99,63,146,36,223,68,
+ 28,107,361,130,99,63,146,36,223,68,
63,20,30,1,1,1,1,1,1,1
);
diff --git a/avx512-0037785/compiler/msgtxt.inc b/avx512-0037785/compiler/msgtxt.inc
index f26b6e9110..7331a50698 100644
--- a/avx512-0037785/compiler/msgtxt.inc
+++ b/avx512-0037785/compiler/msgtxt.inc
@@ -560,862 +560,865 @@ const msgtxt : array[0..000362,1..240] of char=(
'03337_E_Default values can only be specified for value, const and',' co'+
'nstref parameters'#000+
'03338_W_Pointer type "$1" ignored'#000+
- '03339_E_Global Generic template references static symtable'#000+
+ '03339_E_Generic template in interface section references symbol in imp'+
+ 'lementation section'#000+
'03340_UL_Unit $1 has been already compiled meanwhile.'#000+
- '03341_E_Explicit implementation of methods for specializations of gene'+
- 'ri','cs is not allowed'#000+
+ '03341_E_Explicit implementation of method','s for specializations of ge'+
+ 'nerics is not allowed'#000+
'03342_E_Generic methods are not allowed in interfaces'#000+
'03343_E_Generic methods can not be virtual'#000+
'03344_E_Dynamic packages not supported for target OS'#000+
- '03345_E_The HardFloat directive cannot be used if soft float code is g'+
- 'en','erated or fpu emulation is turned on'#000+
+ '03345_E_The HardFloat directive cannot be',' used if soft float code is'+
+ ' generated or fpu emulation is turned on'#000+
'03346_E_Index $1 is not a valid internal function index'#000+
'03347_W_Operator overload hidden by internal operator: "$1" $2 "$3"'#000+
- '03348_E_Thread variables inside classes or records must be class varia'+
- 'bles'#000+
- '0334','9_E_Only static methods and static variables can be referenced t'+
- 'hrough an object type'#000+
+ '03348_E_Thread variables inside classes or recor','ds must be class var'+
+ 'iables'#000+
+ '03349_E_Only static methods and static variables can be referenced thr'+
+ 'ough an object type'#000+
'03350_E_Cannot redeclare C-style variadic function "$1" as external on'+
- ' this platform; make its first declaration already external'#000+
- '03351_E_Unbound custom a','ttribute: "$1".'#000+
+ ' this platform; make its first declaration already ex','ternal'#000+
+ '03351_E_Unbound custom attribute: "$1".'#000+
'03352_E_Enumeration symbols can only have values in the range of -2^31'+
' to 2^31-1'#000+
'03353_W_Enumeration symbols can only have values in the range of -2^31'+
' to 2^31-1'#000+
- '03354_E_Implementing a method for type "$1" declared in anothe','r unit'+
+ '03354_E_Implementing a method f','or type "$1" declared in another unit'+
#000+
'03355_E_Generic constraint not allowed here'#000+
'03356_E_Explicit location is too small for parameter'#000+
'03357_E_Explicit location size is larger than required by parameter'#000+
- '03358_E_Only data registers are supported for explicit location regi','s'+
- 'ter pairs'#000+
+ '03358_E_Only data registers are suppo','rted for explicit location regi'+
+ 'ster pairs'#000+
'03359_E_Only consecutive registers are supported for explicit location'+
' register pairs'#000+
+ '03360_E_Constructors cannot take type parameters'#000+
'04000_E_Type mismatch'#000+
- '04001_E_Incompatible types: got "$1" expected "$2"'#000+
+ '04001_E_Incompatible types: got "$1" expe','cted "$2"'#000+
'04002_E_Type mismatch between "$1" and "$2"'#000+
- '04003_E_Type identifier ex','pected'#000+
+ '04003_E_Type identifier expected'#000+
'04004_E_Variable identifier expected'#000+
'04005_E_Integer expression expected, but got "$1"'#000+
'04006_E_Boolean expression expected, but got "$1"'#000+
- '04007_E_Ordinal expression expected'#000+
+ '04007_E_Ordinal ','expression expected'#000+
'04008_E_Pointer type expected, but got "$1"'#000+
- '04009_E_Class ty','pe expected, but got "$1"'#000+
+ '04009_E_Class type expected, but got "$1"'#000+
'04011_E_Can'#039't evaluate constant expression'#000+
'04012_E_Set elements are not compatible'#000+
'04013_E_Operation not implemented for sets'#000+
- '04014_W_Automatic type conversion from floating type to COMP which is '+
- 'an integer type'#000+
- '04','015_H_Use DIV instead to get an integer result'#000+
+ '04014_W_','Automatic type conversion from floating type to COMP which i'+
+ 's an integer type'#000+
+ '04015_H_Use DIV instead to get an integer result'#000+
'04016_E_String types have to match exactly in $V+ mode'#000+
- '04017_E_Succ or Pred on enums with assignments not possible'#000+
+ '04017_E_Succ or Pred on enums with assignments not possibl','e'#000+
'04018_E_Can'#039't read or write variables of this type'#000+
- '04019_E_Can'#039't use readln or',' writeln on typed file'#000+
+ '04019_E_Can'#039't use readln or writeln on typed file'#000+
'04020_E_Can'#039't use read or write on untyped file.'#000+
'04021_E_Type conflict between set elements'#000+
- '04022_W_lo/hi(dword/qword) returns the upper/lower word/dword'#000+
+ '04022_W_lo/hi(dword/qword) returns the upper/','lower word/dword'#000+
'04023_E_Integer or real expression expected'#000+
- '04024_E_Wrong type ','"$1" in array constructor'#000+
+ '04024_E_Wrong type "$1" in array constructor'#000+
'04025_E_Incompatible type for arg no. $1: Got "$2", expected "$3"'#000+
- '04026_E_Method (variable) and Procedure (variable) are not compatible'#000+
+ '04026_E_Method (variable) and Procedure (variable) are not compatibl','e'+
+ #000+
'04027_E_Illegal constant passed to internal math function'#000+
- '04028_E_Can'#039't take t','he address of constant expressions'#000+
+ '04028_E_Can'#039't take the address of constant expressions'#000+
'04029_E_Argument cannot be assigned to'#000+
'04030_E_Can'#039't assign local procedure/function to procedure variabl'+
'e'#000+
- '04031_E_Can'#039't assign values to an address'#000+
+ '04031_E_Can'#039't assi','gn values to an address'#000+
'04032_E_Can'#039't assign values to const variable'#000+
- '04033_E_Ar','ray type required'#000+
+ '04033_E_Array type required'#000+
'04034_E_Interface type expected, but got "$1"'#000+
'04035_H_Mixing signed expressions and longwords gives a 64bit result'#000+
- '04036_W_Mixing signed expressions and cardinals here may cause a range'+
- ' check error'#000+
- '04037_E_Typecast has dif','ferent size ($1 -> $2) in assignment'#000+
+ '04036_W_Mixing signed expre','ssions and cardinals here may cause a ran'+
+ 'ge check error'#000+
+ '04037_E_Typecast has different size ($1 -> $2) in assignment'#000+
'04038_E_Enums with assignments cannot be used as array index'#000+
'04039_E_Class or Object types "$1" and "$2" are not related'#000+
- '04040_W_Class types "$1" and "$2" are not related'#000+
- '04041_E_Class or interface type ','expected, but got "$1"'#000+
+ '04','040_W_Class types "$1" and "$2" are not related'#000+
+ '04041_E_Class or interface type expected, but got "$1"'#000+
'04042_E_Type "$1" is not completely defined'#000+
'04043_W_String literal has more characters than short string length'#000+
- '04044_W_Comparison might be always false due to range of constant and '+
- 'expression'#000+
- '04045_W_Comparison might',' be always true due to range of constant and'+
- ' expression'#000+
+ '04044_W_Comparison might ','be always false due to range of constant an'+
+ 'd expression'#000+
+ '04045_W_Comparison might be always true due to range of constant and e'+
+ 'xpression'#000+
'04046_W_Constructing a class "$1" with abstract method "$2"'#000+
- '04047_H_The left operand of the IN operator should be byte sized'#000+
- '04048_W_Type size mismatch, possible loss of data / range c','heck erro'+
- 'r'#000+
+ '04047_H_The left operand of the IN operator ','should be byte sized'#000+
+ '04048_W_Type size mismatch, possible loss of data / range check error'#000+
'04049_H_Type size mismatch, possible loss of data / range check error'#000+
'04050_E_The address of an abstract method cannot be taken'#000+
- '04051_E_Assignments to formal parameters and open arrays are not possi'+
- 'ble'#000+
- '04052_E_Constant Expression',' expected'#000+
+ '04051_E_Assignments t','o formal parameters and open arrays are not pos'+
+ 'sible'#000+
+ '04052_E_Constant Expression expected'#000+
'04053_E_Operation "$1" not supported for types "$2" and "$3"'#000+
'04054_E_Illegal type conversion: "$1" to "$2"'#000+
- '04055_H_Conversion between ordinals and pointers is not portable'#000+
- '04056_W_Conversion between ordinals and pointers is not po','rtable'#000+
+ '04055_H_Conversion between ordinals and poi','nters is not portable'#000+
+ '04056_W_Conversion between ordinals and pointers is not portable'#000+
'04057_E_Can'#039't determine which overloaded function to call'#000+
'04058_E_Illegal counter variable'#000+
- '04059_W_Converting constant real value to double for C variable argume'+
- 'nt, add explicit typecast to prevent this.'#000+
- '04060_E_Class or COM interfac','e type expected, but got "$1"'#000+
+ '04059_W_Converting constant real value to double for C variabl','e argu'+
+ 'ment, add explicit typecast to prevent this.'#000+
+ '04060_E_Class or COM interface type expected, but got "$1"'#000+
'04061_E_Constant packed arrays are not yet supported'#000+
'04062_E_Incompatible type for arg no. $1: Got "$2" expected "(Bit)Pack'+
- 'ed Array"'#000+
+ 'ed Arra','y"'#000+
'04063_E_Incompatible type for arg no. $1: Got "$2" expected "(not pack'+
- 'ed) Arr','ay"'#000+
+ 'ed) Array"'#000+
'04064_E_Elements of packed arrays cannot be of a type which need to be'+
' initialised'#000+
'04065_E_Constant packed records and objects are not yet supported'#000+
- '04066_W_Arithmetic "$1" on untyped pointer is unportable to {$T+}, sug'+
- 'gest typecast'#000+
- '040','76_E_Can'#039't take address of a subroutine marked as local'#000+
+ '04066_W','_Arithmetic "$1" on untyped pointer is unportable to {$T+}, s'+
+ 'uggest typecast'#000+
+ '04076_E_Can'#039't take address of a subroutine marked as local'#000+
'04077_E_Can'#039't export subroutine marked as local from a unit'#000+
'04078_E_Type is not automatable: "$1"'#000+
- '04079_H_Converting the operands to "$1" before doing the add could pre'+
- 'vent overflow er','rors.'#000+
+ '04079_','H_Converting the operands to "$1" before doing the add could p'+
+ 'revent overflow errors.'#000+
'04080_H_Converting the operands to "$1" before doing the subtract coul'+
'd prevent overflow errors.'#000+
- '04081_H_Converting the operands to "$1" before doing the multiply coul'+
- 'd prevent overflow errors.'#000+
- '04082_W_Converting pointers to signed in','tegers may result in wrong c'+
- 'omparison results and range errors, use an unsigned type instead.'#000+
+ '04081_H_Converting the operands to "$1" before doing the ','multiply co'+
+ 'uld prevent overflow errors.'#000+
+ '04082_W_Converting pointers to signed integers may result in wrong com'+
+ 'parison results and range errors, use an unsigned type instead.'#000+
'04083_E_Interface type $1 has no valid GUID'#000+
- '04084_E_Invalid selector name "$1"'#000+
+ '04084_E_Invalid select','or name "$1"'#000+
'04085_E_Expected Objective-C method, but got $1'#000+
- '04086_E_Expected Ob','jective-C method or constant method name'#000+
+ '04086_E_Expected Objective-C method or constant method name'#000+
'04087_E_No type info available for this type'#000+
'04088_E_Ordinal or string expression expected'#000+
- '04089_E_String expression expected'#000+
+ '04089_E_String expression ex','pected'#000+
'04090_W_Converting 0 to NIL'#000+
- '04091_E_Objective-C protocol type expected, b','ut got "$1"'#000+
+ '04091_E_Objective-C protocol type expected, but got "$1"'#000+
'04092_E_The type "$1" is not supported for interaction with the Object'+
'ive-C and the blocks runtime.'#000+
- '04093_E_Class or objcclass type expected, but got "$1"'#000+
+ '04093_E_Class or objcclass type expected, but go','t "$1"'#000+
'04094_E_Objcclass type expected'#000+
- '04095_W_Coerced univ parameter type in pr','ocedural variable may cause'+
- ' crash or memory corruption: $1 to $2'#000+
+ '04095_W_Coerced univ parameter type in procedural variable may cause c'+
+ 'rash or memory corruption: $1 to $2'#000+
'04096_E_Type parameters of specializations of generics cannot referenc'+
- 'e the currently specialized type'#000+
+ 'e the currently specializ','ed type'#000+
'04097_E_Type parameters are not allowed on non-generic class/record/ob'+
- 'je','ct procedure or function'#000+
+ 'ject procedure or function'#000+
'04098_E_Generic declaration of "$1" differs from previous declaration'#000+
'04099_E_Helper type expected'#000+
'04100_E_Record type expected'#000+
- '04101_E_Derived class helper must extend a subclass of "$1" or the cla'+
- 'ss itself'#000+
- '04102_E','_Derived record or type helper must extend "$1"'#000+
+ '04101_E','_Derived class helper must extend a subclass of "$1" or the c'+
+ 'lass itself'#000+
+ '04102_E_Derived record or type helper must extend "$1"'#000+
'04103_E_Invalid assignment, procedures return no value'#000+
- '04104_W_Implicit string type conversion from "$1" to "$2"'#000+
+ '04104_W_Implicit string type conversion from "$1" to "$2"',#000+
'04105_W_Implicit string type conversion with potential data loss from '+
- '"$1" to "','$2"'#000+
+ '"$1" to "$2"'#000+
'04106_-W_Explicit string typecast from "$1" to "$2"'#000+
'04107_-W_Explicit string typecast with potential data loss from "$1" t'+
'o "$2"'#000+
- '04108_W_Unicode constant cast with potential data loss'#000+
- '04109_E_Range check error while evaluating constants',' ($1 must be bet'+
- 'ween $2 and $3)'#000+
+ '04108_W_Unicode constant ca','st with potential data loss'#000+
+ '04109_E_Range check error while evaluating constants ($1 must be betwe'+
+ 'en $2 and $3)'#000+
'04110_W_Range check error while evaluating constants ($1 must be betwe'+
'en $2 and $3)'#000+
- '04111_E_This type is not supported for the Default() intrinsic'#000+
+ '04111_E_This type is not supported for the D','efault() intrinsic'#000+
'04112_E_JVM virtual class methods cannot be static'#000+
- '04113_E_Fi','nal (class) fields can only be assigned in their class'#039+
- ' (class) constructor'#000+
+ '04113_E_Final (class) fields can only be assigned in their class'#039' '+
+ '(class) constructor'#000+
'04114_E_It is not possible to typecast untyped parameters on managed p'+
- 'latforms, simply assign a value to them instead.'#000+
- '04115_E_The assignment side of an expression ','cannot be typecasted to'+
- ' a supertype on managed platforms'#000+
+ 'latforms, simp','ly assign a value to them instead.'#000+
+ '04115_E_The assignment side of an expression cannot be typecasted to a'+
+ ' supertype on managed platforms'#000+
'04116_-W_The interface method "$1" raises the visibility of "$2" to pu'+
- 'blic when accessed via an interface instance'#000+
- '04117_E_The interface method "$1" has a higher visibility (public) t','h'+
- 'an "$2"'#000+
+ 'blic when accessed via an interfa','ce instance'#000+
+ '04117_E_The interface method "$1" has a higher visibility (public) tha'+
+ 'n "$2"'#000+
'04118_E_TYPEOF can only be used on object types with VMT'#000+
'04119_E_It is not possible to define a default value for a parameter o'+
'f type "$1"'#000+
- '04120_E_Type "$1" cannot be extended by a type helper'#000+
- '04121_E_Procedure or function must be ','far in order to allow taking i'+
- 'ts address: "$1"'#000+
+ '04120_E_Type',' "$1" cannot be extended by a type helper'#000+
+ '04121_E_Procedure or function must be far in order to allow taking its'+
+ ' address: "$1"'#000+
'04122_W_Creating an instance of abstract class "$1"'#000+
- '04123_E_Subroutine references cannot be declared as "of object" or "is'+
- ' nested", they can always refer to any kind of subroutine'#000+
- '04124_E_Proce','dure variables in that memory model do not store segmen'+
- 't information'#000+
+ '04123_E_Subroutine references cannot be declared as "of objec','t" or "'+
+ 'is nested", they can always refer to any kind of subroutine'#000+
+ '04124_E_Procedure variables in that memory model do not store segment '+
+ 'information'#000+
'04125_W_The first value of a set constructur range is greater then the'+
- ' second value, so the range describes an empty set.'#000+
- '04126_E_C block reference must use CDECL or MWPAS','CAL calling convent'+
- 'ion.'#000+
+ ' second value, so the',' range describes an empty set.'#000+
+ '04126_E_C block reference must use CDECL or MWPASCAL calling conventio'+
+ 'n.'#000+
'04127_E_The interface type of the forward declaration and the declared'+
' interface type do not match for interface $1'#000+
- '04128_E_Type not allowed for generic constant parameter: $1'#000+
- '04129_E_Can'#039't read or write variables of',' this type in iso mode'#000+
+ '04128_E_Type not all','owed for generic constant parameter: $1'#000+
+ '04129_E_Can'#039't read or write variables of this type in iso mode'#000+
'05000_E_Identifier not found "$1"'#000+
'05001_F_Internal Error in SymTableStack()'#000+
'05002_E_Duplicate identifier "$1"'#000+
- '05003_H_Identifier already defined in $1 at line $2'#000+
+ '05003_H_Identifier already ','defined in $1 at line $2'#000+
'05004_E_Unknown identifier "$1"'#000+
- '05005_E_Forward declara','tion not solved "$1"'#000+
+ '05005_E_Forward declaration not solved "$1"'#000+
'05007_E_Error in type definition'#000+
'05009_E_Forward type not resolved "$1"'#000+
- '05010_E_Only static variables can be used in static methods or outside'+
- ' methods'#000+
+ '05010_E_Only static variables can be used in static methods or outs','i'+
+ 'de methods'#000+
'05012_E_Record or object or class type expected'#000+
- '05013_E_Instances of',' classes or objects with an abstract method are '+
- 'not allowed'#000+
+ '05013_E_Instances of classes or objects with an abstract method are no'+
+ 't allowed'#000+
'05014_W_Label not defined "$1"'#000+
'05015_E_Label used but not defined "$1"'#000+
- '05016_E_Illegal label declaration'#000+
+ '05016_E_Illegal label declara','tion'#000+
'05017_E_GOTO and LABEL are not supported (use switch -Sg)'#000+
- '05018_E_Label not',' found'#000+
+ '05018_E_Label not found'#000+
'05019_E_Identifier isn'#039't a label'#000+
'05020_E_Label already defined'#000+
'05021_E_Illegal type declaration of set elements'#000+
- '05022_E_Forward class definition not resolved "$1"'#000+
+ '05022_E_Forward class definition not reso','lved "$1"'#000+
'05023_H_Unit "$1" not used in $2'#000+
'05024_H_Parameter "$1" not used'#000+
- '05025','_N_Local variable "$1" not used'#000+
+ '05025_N_Local variable "$1" not used'#000+
'05026_H_Value parameter "$1" is assigned but never used'#000+
'05027_N_Local variable "$1" is assigned but never used'#000+
- '05028_H_Local $1 "$2" is not used'#000+
+ '05028_H_Local $1 ','"$2" is not used'#000+
'05029_N_Private field "$1.$2" is never used'#000+
- '05030_N_Private fie','ld "$1.$2" is assigned but never used'#000+
+ '05030_N_Private field "$1.$2" is assigned but never used'#000+
'05031_N_Private method "$1.$2" never used'#000+
'05032_E_Set type expected'#000+
'05033_W_Function result does not seem to be set'#000+
- '05034_W_Type "$1" is not aligned correctly in current record for C'#000+
- '05035_E_Unknown rec','ord field identifier "$1"'#000+
+ '05034_','W_Type "$1" is not aligned correctly in current record for C'#000+
+ '05035_E_Unknown record field identifier "$1"'#000+
'05036_W_Local variable "$1" does not seem to be initialized'#000+
'05037_W_Variable "$1" does not seem to be initialized'#000+
- '05038_E_Identifier idents no member "$1"'#000+
+ '05038_E_Identifier i','dents no member "$1"'#000+
'05039_H_Found declaration: $1'#000+
- '05040_E_Data element too larg','e'#000+
+ '05040_E_Data element too large'#000+
'05042_E_No matching implementation for interface method "$1" found'#000+
'05043_W_Symbol "$1" is deprecated'#000+
'05044_W_Symbol "$1" is not portable'#000+
- '05055_W_Symbol "$1" is not implemented'#000+
+ '05055_W_Symbol "$1" i','s not implemented'#000+
'05056_E_Can'#039't create unique type from this type'#000+
- '05057_H_Local ','variable "$1" does not seem to be initialized'#000+
+ '05057_H_Local variable "$1" does not seem to be initialized'#000+
'05058_H_Variable "$1" does not seem to be initialized'#000+
- '05059_W_Function result variable does not seem to be initialized'#000+
+ '05059_W_Function result variable does not seem to be initial','ized'#000+
'05060_H_Function result variable does not seem to be initialized'#000+
- '05061_W_Va','riable "$1" read but nowhere assigned'#000+
+ '05061_W_Variable "$1" read but nowhere assigned'#000+
'05062_H_Found abstract method: $1'#000+
'05063_W_Symbol "$1" is experimental'#000+
- '05064_W_Forward declaration "$1" not resolved, assumed external'#000+
+ '05064_W_Forward declaration "$1" not resolved, assum','ed external'#000+
'05065_W_Symbol "$1" is belongs to a library'#000+
- '05066_W_Symbol "$1" is d','eprecated: "$2"'#000+
+ '05066_W_Symbol "$1" is deprecated: "$2"'#000+
'05067_E_Cannot find an enumerator for the type "$1"'#000+
'05068_E_Cannot find a "MoveNext" method in enumerator "$1"'#000+
- '05069_E_Cannot find a "Current" property in enumerator "$1"'#000+
- '05070_E_Mismatch between number of declared parameter','s and number of'+
- ' colons in message string.'#000+
+ '05069_E_Cannot find a "Current" p','roperty in enumerator "$1"'#000+
+ '05070_E_Mismatch between number of declared parameters and number of c'+
+ 'olons in message string.'#000+
'05071_N_Private type "$1.$2" never used'#000+
'05072_N_Private const "$1.$2" never used'#000+
- '05073_N_Private property "$1.$2" never used'#000+
+ '05073_N_Private property "$1.$2" neve','r used'#000+
'05074_W_Unit "$1" is deprecated'#000+
'05075_W_Unit "$1" is deprecated: "$2"'#000+
- '050','76_W_Unit "$1" is not portable'#000+
+ '05076_W_Unit "$1" is not portable'#000+
'05077_W_Unit "$1" is belongs to a library'#000+
'05078_W_Unit "$1" is not implemented'#000+
'05079_W_Unit "$1" is experimental'#000+
- '05080_E_No full definition of the formally declared class "$1" is in s'+
- 'cope. Add the unit contain','ing its full definition to the uses clause'+
+ '05080_E_No full ','definition of the formally declared class "$1" is in'+
+ ' scope. Add the unit containing its full definition to the uses clause'+
'.'#000+
'05081_E_Gotos into initialization or finalization blocks of units are '+
'not allowed'#000+
- '05082_E_Invalid external name "$1" for formal class "$2"'#000+
- '05083_E_Complete class definition with external name "$1"',' here'#000+
+ '05082_E_Invalid external name "$1"',' for formal class "$2"'#000+
+ '05083_E_Complete class definition with external name "$1" here'#000+
'05084_W_Possible library conflict: symbol "$1" from library "$2" also '+
'found in library "$3"'#000+
- '05085_E_Cannot add implicit constructor '#039'Create'#039' because ident'+
+ '05085_E_Cannot add implicit constructor '#039'Create'#039' because ident',
'ifier already used by "$1"'#000+
- '05086_E_Cannot generate default constructor for class',', because paren'+
- 't has no parameterless constructor'#000+
+ '05086_E_Cannot generate default constructor for class, because parent '+
+ 'has no parameterless constructor'#000+
'05087_D_Adding helper for $1'#000+
'05088_E_Found declaration: $1'#000+
- '05089_W_Local variable "$1" of a managed type does not seem to be init'+
- 'ialized'#000+
- '05090_W_Variable "$1" of a managed type does not seem',' to be initiali'+
- 'zed'#000+
+ '05089_W_Local variable "$1" of a managed type does ','not seem to be in'+
+ 'itialized'#000+
+ '05090_W_Variable "$1" of a managed type does not seem to be initialize'+
+ 'd'#000+
'05091_H_Local variable "$1" of a managed type does not seem to be init'+
'ialized'#000+
- '05092_H_Variable "$1" of a managed type does not seem to be initialize'+
- 'd'#000+
+ '05092_H_Variable "$1" of a managed type does not seem to be ini','tiali'+
+ 'zed'#000+
'05093_W_Function result variable of a managed type does not seem to be'+
- ' ','initialized'#000+
+ ' initialized'#000+
'05094_H_Function result variable of a managed type does not seem to be'+
' initialized'#000+
'05095_W_Duplicate identifier "$1"'#000+
- '05096_E_Generic type parameter "$1" does not match with the one in the'+
- ' declaration'#000+
- '05097_E_Generic type paramet','er declared as "$1"'#000+
+ '05096_E_Generic type parameter ','"$1" does not match with the one in t'+
+ 'he declaration'#000+
+ '05097_E_Generic type parameter declared as "$1"'#000+
'05098_E_Record or object type expected'#000+
'06009_E_Parameter list size exceeds 65535 bytes'#000+
'06012_E_File types must be var parameters'#000+
- '06013_E_The use of a far pointer isn'#039't allowed there'#000+
- '06015_E_EXPORT declared functions cann','ot be called'#000+
+ '06013_E_The',' use of a far pointer isn'#039't allowed there'#000+
+ '06015_E_EXPORT declared functions cannot be called'#000+
'06016_W_Possible illegal call of constructor or destructor'#000+
'06017_N_Inefficient code'#000+
'06018_W_Unreachable code'#000+
- '06020_E_Abstract methods cannot be called directly'#000+
+ '06020_E_Abstract methods cannot be cal','led directly'#000+
'06027_DL_Register $1 weight $2 $3'#000+
'06029_DL_Stack frame is omitted'#000+
- '0','6031_E_Object or class methods cannot be inline.'#000+
+ '06031_E_Object or class methods cannot be inline.'#000+
'06032_E_Procvar calls cannot be inline.'#000+
'06033_E_No code for inline procedure stored'#000+
- '06035_E_Element zero of an ansi/wide- or longstring cannot be accessed'+
- ', use (set)length instead'#000+
- '06037_E_Con','structors or destructors cannot be called inside a '#039'w'+
- 'ith'#039' clause'#000+
+ '06035_E_Element zero of an ','ansi/wide- or longstring cannot be access'+
+ 'ed, use (set)length instead'#000+
+ '06037_E_Constructors or destructors cannot be called inside a '#039'wit'+
+ 'h'#039' clause'#000+
'06038_E_Cannot call message handler methods directly'#000+
- '06039_E_Jump in or outside of an exception block'#000+
+ '06039_E_Jump in or outside of an exception',' block'#000+
'06040_E_Control flow statements are not allowed in a finally block'#000+
- '06041_','W_Parameters size exceeds limit for certain cpu'#039's'#000+
+ '06041_W_Parameters size exceeds limit for certain cpu'#039's'#000+
'06042_W_Local variable size exceed limit for certain cpu'#039's'#000+
- '06043_E_Local variables size exceeds supported limit'#000+
+ '06043_E_Local variables size exceeds supported limi','t'#000+
'06044_E_BREAK not allowed'#000+
'06045_E_CONTINUE not allowed'#000+
- '06046_F_Unknown compile','rproc "$1". Check if you use the correct run '+
- 'time library.'#000+
+ '06046_F_Unknown compilerproc "$1". Check if you use the correct run ti'+
+ 'me library.'#000+
'06047_F_Cannot find system type "$1". Check if you use the correct run'+
' time library.'#000+
- '06048_H_Inherited call to abstract method ignored'#000+
- '06049_E_Goto label "$1" not defined or optimiz','ed away'#000+
+ '06048_H_Inherite','d call to abstract method ignored'#000+
+ '06049_E_Goto label "$1" not defined or optimized away'#000+
'06050_F_Cannot find type "$1" in unit "$2". Check if you use the corre'+
'ct run time library.'#000+
- '06051_E_Interprocedural gotos are allowed only to outer subroutines'#000+
+ '06051_E_Interprocedural gotos are allowed only to outer subro','utines'#000+
'06052_E_Label must be defined in the same scope as it is declared'#000+
- '06053_E','_Leaving procedures containing explicit or implicit exception'+
- 's frames using goto is not allowed'#000+
- '06054_E_In ISO mode, the mod operator is defined only for positive quo'+
- 'tient'#000+
+ '06053_E_Leaving procedures containing explicit or implicit exceptions '+
+ 'frames using goto is not allowed'#000+
+ '06054_E_In ISO mode, the mod operator is defined only for positi','ve q'+
+ 'uotient'#000+
'06055_DL_Auto inlining: $1'#000+
- '06056_E_The function used, is not support','ed by the selected instruct'+
- 'ion set: $1'#000+
+ '06056_E_The function used, is not supported by the selected instructio'+
+ 'n set: $1'#000+
'06057_F_Maximum number of units ($1) reached for the current target'#000+
- '06058_N_Call to subroutine "$1" marked as inline is not inlined'#000+
- '06059_E_Case statement does not handle ordinal value "$1", and no els',
- 'e/otherwise statement is present.'#000+
+ '06058_N_Call to subroutine "$1" marked as inline is n','ot inlined'#000+
+ '06059_E_Case statement does not handle ordinal value "$1", and no else'+
+ '/otherwise statement is present.'#000+
'06060_W_Case statement does not handle all possible cases'#000+
- '06061_W_The current subroutine "$1" cannot be compiled for the target '+
- 'CPU, creating dummy'#000+
- '06062_W_The target CPU does not support preserving the reg','isters in '+
- 'subroutine "$1"'#000+
+ '06061_W_The current subroutine "$1" cannot be compiled for the targe','t'+
+ ' CPU, creating dummy'#000+
+ '06062_W_The target CPU does not support preserving the registers in su'+
+ 'broutine "$1"'#000+
'07000_DL_Starting $1 styled assembler parsing'#000+
'07001_DL_Finished $1 styled assembler parsing'#000+
'07002_E_Non-label pattern contains @'#000+
- '07004_E_Error building record offset'#000+
+ '07004','_E_Error building record offset'#000+
'07005_E_OFFSET used without identifier'#000+
- '07006_E_T','YPE used without identifier'#000+
+ '07006_E_TYPE used without identifier'#000+
'07007_E_Cannot use local variable or parameters here'#000+
'07008_E_Need to use OFFSET here'#000+
'07009_E_Need to use $ here'#000+
- '07010_E_Cannot use multiple relocatable symbols'#000+
+ '07010_E_Cannot use m','ultiple relocatable symbols'#000+
'07011_E_Relocatable symbol can only be added'#000+
- '07012_E','_Invalid constant expression'#000+
+ '07012_E_Invalid constant expression'#000+
'07013_E_Relocatable symbol is not allowed'#000+
'07014_E_Invalid reference syntax'#000+
'07015_E_You cannot reach $1 from that code'#000+
- '07016_E_Local symbols/labels are not allowed as references'#000+
- '07017_E_Invalid base and index reg','ister usage'#000+
+ '07016_E_Local',' symbols/labels are not allowed as references'#000+
+ '07017_E_Invalid base and index register usage'#000+
'07018_W_Possible error in object field handling'#000+
'07019_E_Wrong scale factor specified'#000+
'07020_E_Multiple index register usage'#000+
- '07021_E_Invalid operand type'#000+
+ '07021_E_Invalid operand t','ype'#000+
'07022_E_Invalid string as opcode operand: $1'#000+
- '07023_W_@CODE and @DATA not sup','ported'#000+
+ '07023_W_@CODE and @DATA not supported'#000+
'07024_E_Null label references are not allowed'#000+
'07025_E_Divide by zero in asm evaluator'#000+
'07026_E_Illegal expression'#000+
'07027_E_Escape sequence ignored: $1'#000+
- '07028_E_Invalid symbol reference'#000+
- '07029_W_Fwait can cause emulation problems with emu','387'#000+
+ '0702','8_E_Invalid symbol reference'#000+
+ '07029_W_Fwait can cause emulation problems with emu387'#000+
'07030_W_$1 without operand translated into $1P'#000+
'07031_W_ENTER instruction is not supported by Linux kernel'#000+
- '07032_W_Calling an overload function in assembler'#000+
+ '07032_W_Calling an overload function in assembler'#000,
'07033_E_Unsupported symbol type for operand'#000+
- '07034_E_Constant value out of bounds',#000+
+ '07034_E_Constant value out of bounds'#000+
'07035_E_Error converting decimal $1'#000+
'07036_E_Error converting octal $1'#000+
'07037_E_Error converting binary $1'#000+
'07038_E_Error converting hexadecimal $1'#000+
- '07039_H_$1 translated to $2'#000+
+ '07039_H_$1 tra','nslated to $2'#000+
'07040_W_$1 is associated to an overloaded function'#000+
- '07041_E_Cannot ','use SELF outside a method'#000+
+ '07041_E_Cannot use SELF outside a method'#000+
'07042_E_Cannot use OLDEBP outside a nested procedure'#000+
'07043_W_Procedures cannot return any value in asm code'#000+
- '07044_E_SEG not supported'#000+
+ '07044_E_SEG not supported'#000,
'07045_E_Size suffix and destination or source size do not match'#000+
- '07046_W_Size suf','fix and destination or source size do not match'#000+
+ '07046_W_Size suffix and destination or source size do not match'#000+
'07047_E_Assembler syntax error'#000+
'07048_E_Invalid combination of opcode and operands'#000+
- '07049_E_Assembler syntax error in operand'#000+
+ '07049_E_Assembler syntax error',' in operand'#000+
'07050_E_Assembler syntax error in constant'#000+
- '07051_E_Invalid String ex','pression'#000+
+ '07051_E_Invalid String expression'#000+
'07052_W_Constant with symbol $1 for address which is not on a pointer'#000+
'07053_E_Unrecognized opcode $1'#000+
'07054_E_Invalid or missing opcode'#000+
- '07055_E_Invalid combination of prefix and opcode: $1'#000+
- '07056_E_Invalid combination of override and',' opcode: $1'#000+
+ '07055_E_Invalid ','combination of prefix and opcode: $1'#000+
+ '07056_E_Invalid combination of override and opcode: $1'#000+
'07057_E_Too many operands on line'#000+
'07058_W_NEAR ignored'#000+
'07059_W_FAR ignored'#000+
'07060_E_Duplicate local symbol $1'#000+
'07061_E_Undefined local symbol $1'#000+
- '07062_E_Unknown label identifier $1'#000+
+ '07062','_E_Unknown label identifier $1'#000+
'07063_E_Invalid register name'#000+
- '07064_E_Invalid flo','ating point register name'#000+
+ '07064_E_Invalid floating point register name'#000+
'07066_W_Modulo not supported'#000+
'07067_E_Invalid floating point constant $1'#000+
'07068_E_Invalid floating point expression'#000+
- '07069_E_Wrong symbol type'#000+
+ '07069_E_Wrong symbol',' type'#000+
'07070_E_Cannot index a local var or parameter with a register'#000+
- '07071_E_Inva','lid segment override expression'#000+
+ '07071_E_Invalid segment override expression'#000+
'07072_W_Identifier $1 supposed external'#000+
'07073_E_Strings not allowed as constants'#000+
'07074_E_No type of variable specified'#000+
- '07075_E_Assembler code not returned to text section'#000+
- '07076_E_Not a directive or local symb','ol $1'#000+
+ '07075_E_A','ssembler code not returned to text section'#000+
+ '07076_E_Not a directive or local symbol $1'#000+
'07077_E_Using a defined name as a local label'#000+
'07078_E_Dollar token is used without an identifier'#000+
'07079_W_32bit constant created for address'#000+
- '07080_N_.align is target specific, use .balign or .p2align'#000+
- '07081_E_Cannot directly access fiel','ds of pointer-based parameters'#000+
+ '07080_N_.align',' is target specific, use .balign or .p2align'#000+
+ '07081_E_Cannot directly access fields of pointer-based parameters'#000+
'07082_E_Can'#039't access fields of objects/classes directly'#000+
'07083_E_No size specified and unable to determine the size of the oper'+
- 'ands'#000+
+ 'and','s'#000+
'07084_E_Cannot use RESULT in this function'#000+
- '07086_W_"$1" without operand transl','ated into "$1 %st,%st(1)"'#000+
+ '07086_W_"$1" without operand translated into "$1 %st,%st(1)"'#000+
'07087_W_"$1 %st(n)" translated into "$1 %st,%st(n)"'#000+
'07088_W_"$1 %st(n)" translated into "$1 %st(n),%st"'#000+
- '07089_E_Char < not allowed here'#000+
+ '07089_E_Char < not allowed her','e'#000+
'07090_E_Char > not allowed here'#000+
'07093_W_ALIGN not supported'#000+
- '07094_E_Inc and De','c cannot be together'#000+
+ '07094_E_Inc and Dec cannot be together'#000+
'07095_E_Invalid register list for MOVEM or FMOVEM'#000+
'07096_E_Reglist invalid for opcode'#000+
'07097_E_Higher cpu mode required ($1)'#000+
- '07098_W_No size specified and unable to determine the size of the oper'+
- 'ands, using DWORD as defau','lt'#000+
+ '07098_W_No size ','specified and unable to determine the size of the op'+
+ 'erands, using DWORD as default'#000+
'07099_E_Syntax error while trying to parse a shifter operand'#000+
'07100_E_Address of packed component is not at a byte boundary'#000+
- '07101_W_No size specified and unable to determine the size of the oper'+
- 'ands, using BYTE as default'#000+
- '07102_W_Use of $','1 for parameters invalid here'#000+
+ '07101_W_No size specified and unab','le to determine the size of the op'+
+ 'erands, using BYTE as default'#000+
+ '07102_W_Use of $1 for parameters invalid here'#000+
'07103_W_Use of $1 is not compatible with regcall convention'#000+
'07104_W_Use of $1 is not recommended for local variable access'#000+
- '07105_W_Use of $1, access may cause a crash or value may be lost'#000+
- '07106_E_VMTOffset must',' be used in combination with a virtual method,'+
- ' and "$1" is not virtual'#000+
+ '07105_W','_Use of $1, access may cause a crash or value may be lost'#000+
+ '07106_E_VMTOffset must be used in combination with a virtual method, a'+
+ 'nd "$1" is not virtual'#000+
'07107_E_Generating PIC, but reference is not PIC-safe'#000+
- '07108_E_All registers in a register set must be of the same kind and w'+
- 'idth'#000+
+ '07108_E_All registers in a register',' set must be of the same kind and'+
+ ' width'#000+
'07109_E_A register set cannot be empty'#000+
- '0','7110_W_@GOTPCREL is useless and potentially dangerous for local sym'+
- 'bols'#000+
+ '07110_W_@GOTPCREL is useless and potentially dangerous for local symbo'+
+ 'ls'#000+
'07111_W_Constant with general purpose segment register'#000+
- '07112_E_Invalid offset value for $1'#000+
+ '07112_E_Invalid offset value for ','$1'#000+
'07113_E_Invalid register for $1'#000+
- '07114_E_SEH directives are allowed only in pu','re assembler procedures'+
- #000+
+ '07114_E_SEH directives are allowed only in pure assembler procedures'#000+
'07115_E_Directive "$1" is not supported for the current target'#000+
'07116_E_This function'#039's result location cannot be encoded directly'+
- ' in a single operand when "nostackframe" is used'#000+
- '07117_E_GOTPCREL references in Intel a','ssembler syntax cannot contain'+
- ' a base or index register, and their offset must 0.'#000+
+ ' in a s','ingle operand when "nostackframe" is used'#000+
+ '07117_E_GOTPCREL references in Intel assembler syntax cannot contain a'+
+ ' base or index register, and their offset must 0.'#000+
'07118_E_The current target does not support GOTPCREL relocations'#000+
- '07119_W_Exported/global symbols should be accessed via the GOT'#000+
- '07120_W_Check size of memory o','perand "$1"'#000+
+ '07119_W_Expor','ted/global symbols should be accessed via the GOT'#000+
+ '07120_W_Check size of memory operand "$1"'#000+
'07121_W_Check size of memory operand "$1: memory-operand-size is $2 bi'+
'ts, but expected [$3 bits]"'#000+
- '07122_W_Check size of memory operand "$1: memory-operand-size is $2 bi'+
- 'ts, but expected [$3 bits + $4 byte offset]"'#000+
- '07123_W_Check "','$1: offset of memory operand is negative "$2 byte"'#000+
+ '07122_W_Check size of memory operand "$1: memory-o','perand-size is $2 '+
+ 'bits, but expected [$3 bits + $4 byte offset]"'#000+
+ '07123_W_Check "$1: offset of memory operand is negative "$2 byte"'#000+
'07124_W_Check "$1: size of memory operand is empty, but es exists diff'+
- 'erent definitions of the memory size =>> map to $2 (smallest option)"'#000+
- '07125_E_Invalid register used in memory reference',' expression: "$1"'#000+
+ 'erent definitions of the memory size =>','> map to $2 (smallest option)'+
+ '"'#000+
+ '07125_E_Invalid register used in memory reference expression: "$1"'#000+
'07126_E_SEG used without identifier'#000+
'07127_E_@CODE and @DATA can only be used with the SEG operator'#000+
- '07128_E_Not enough space (16 bits required) for the segment constant o'+
- 'f symbol $1'#000+
- '07129_E_Invalid value of .code directive ','constant'#000+
+ '07128_E_Not enough space (16 bits required)',' for the segment constant'+
+ ' of symbol $1'#000+
+ '07129_E_Invalid value of .code directive constant'#000+
'07130_W_No size specified and unable to determine the size of the cons'+
'tant, using BYTE as default'#000+
- '07131_W_No size specified and unable to determine the size of the cons'+
- 'tant, using WORD as default'#000+
- '07132_E_Cannot override ES segment'#000,
+ '07131_W_No size specified and unable to determine the',' size of the co'+
+ 'nstant, using WORD as default'#000+
+ '07132_E_Cannot override ES segment'#000+
'07133_W_Reference is not valid here (expected "$1")'#000+
'07134_E_Address sizes do not match'#000+
'07135_E_Instruction "POP CS" is not valid for the current target'#000+
- '07136_W_Instruction "POP CS" is not portable (it only works on 8086 an'+
- 'd 8088 CPUs)'#000+
- '07137','_E_Label $1 can only be declared public before it'#039's defined'+
- #000+
+ '07136_W_','Instruction "POP CS" is not portable (it only works on 8086 '+
+ 'and 8088 CPUs)'#000+
+ '07137_E_Label $1 can only be declared public before it'#039's defined'#000+
'07138_E_Local label $1 cannot be declared public'#000+
'07139_E_Cannot use multiple segment overrides'#000+
- '07140_W_Multiple segment overrides (only the last one will take effect'+
- ')'#000+
- '07141_W_Segme','nt base $1 will be generated, but is ignored by the CPU'+
- ' in 64-bit mode'#000+
+ '07140','_W_Multiple segment overrides (only the last one will take effe'+
+ 'ct)'#000+
+ '07141_W_Segment base $1 will be generated, but is ignored by the CPU i'+
+ 'n 64-bit mode'#000+
'07142_E_Mismatch broadcasting elements (expected: {$1} found: {$2})'#000+
- '07143_E_Invalid arrangement specifier "$1"'#000+
+ '07143_E_Invalid arran','gement specifier "$1"'#000+
'07144_E_Registers in a register set must be consecutive.'#000+
- '0','7145_E_Not supported combination opcode: $1 - att-suffix-type {$2} '+
- 'and memrefsize-type {$3}'#000+
+ '07145_E_Not supported combination opcode: $1 - att-suffix-type {$2} an'+
+ 'd memrefsize-type {$3}'#000+
'08000_F_Too many assembler files'#000+
- '08001_F_Selected assembler output not supported'#000+
+ '08001_F_Selected assembler output n','ot supported'#000+
'08002_F_Comp not supported'#000+
- '08003_F_Direct not support for binary wr','iters'#000+
+ '08003_F_Direct not support for binary writers'#000+
'08004_E_Allocating of data is only allowed in bss section'#000+
'08005_F_No binary writer selected'#000+
'08006_E_Asm: Opcode $1 not in table'#000+
- '08007_E_Asm: $1 invalid combination of opcode and operands'#000+
+ '08007_E_Asm: $1 invalid co','mbination of opcode and operands'#000+
'08008_E_Asm: 16 Bit references not supported'#000+
- '08','009_E_Asm: Invalid effective address'#000+
+ '08009_E_Asm: Invalid effective address'#000+
'08010_E_Asm: Immediate or reference expected'#000+
'08011_E_Asm: $1 value exceeds bounds $2'#000+
- '08012_E_Asm: Short jump is out of range $1'#000+
+ '08012_E_Asm: Short jump is out of rang','e $1'#000+
'08013_E_Asm: Undefined label $1'#000+
- '08014_E_Asm: Comp type not supported for th','is target'#000+
+ '08014_E_Asm: Comp type not supported for this target'#000+
'08015_E_Asm: Extended type not supported for this target'#000+
'08016_E_Asm: Duplicate label $1'#000+
'08017_E_Asm: Redefined label $1'#000+
- '08018_E_Asm: First defined here'#000+
+ '08018_E_Asm: First defined he','re'#000+
'08019_E_Asm: Invalid register $1'#000+
- '08020_E_Asm: 16 or 32 Bit references not sup','ported'#000+
+ '08020_E_Asm: 16 or 32 Bit references not supported'#000+
'08021_E_Asm: 64 Bit operands not supported'#000+
'08022_E_Asm: AH,BH,CH or DH cannot be used in an instruction requiring'+
' REX prefix'#000+
- '08023_E_Missing .seh_endprologue directive'#000+
+ '08023_E_Missing .seh_endprol','ogue directive'#000+
'08024_E_Function prologue exceeds 255 bytes'#000+
- '08025_E_.seh_handlerd','ata directive without preceding .seh_handler'#000+
+ '08025_E_.seh_handlerdata directive without preceding .seh_handler'#000+
'08026_F_Relocation count for section $1 exceeds 65535'#000+
- '08027_N_Change of bind type of symbol $1 from $2 to $3 after use'#000+
+ '08027_N_Change of bind type of symbol $1 from $2 to $3 after ','use'#000+
'08028_H_Change of bind type of symbol $1 from $2 to $3 after use'#000+
- '08029_E_Asm',': 32 Bit references not supported'#000+
+ '08029_E_Asm: 32 Bit references not supported'#000+
'08030_F_Code segment too large'#000+
'08031_F_Data segment too large'#000+
- '08032_E_Instruction not supported by the selected instruction set'#000+
+ '08032_E_Instruction not supported by the selected instruction se','t'#000+
'08033_E_Asm: conditional branch destination is out of range'#000+
- '08034_E_Asm: RIP c','annot be used as index register or with another re'+
- 'gister in a reference'#000+
+ '08034_E_Asm: RIP cannot be used as index register or with another regi'+
+ 'ster in a reference'#000+
'08035_F_Illegal function size for SEH function'#000+
- '09000_W_Source operating system redefined'#000+
+ '09000_W_Source operating system redefined',#000+
'09001_I_Assembling (pipe) $1'#000+
'09002_E_Can'#039't create assembler file: $1'#000+
- '09003_E_Ca','n'#039't create object file: $1 (error code: $2)'#000+
+ '09003_E_Can'#039't create object file: $1 (error code: $2)'#000+
'09004_E_Can'#039't create archive file: $1'#000+
'09005_E_Assembler $1 not found, switching to external assembling'#000+
- '09006_T_Using assembler: $1'#000+
+ '09006_T_Using',' assembler: $1'#000+
'09007_E_Error while assembling exitcode $1'#000+
- '09008_E_Can'#039't call the',' assembler, error $1 switching to external'+
- ' assembling'#000+
+ '09008_E_Can'#039't call the assembler, error $1 switching to external a'+
+ 'ssembling'#000+
'09009_I_Assembling $1'#000+
'09010_I_Assembling with smartlinking $1'#000+
- '09011_W_Object $1 not found, Linking may fail !'#000+
+ '09011_W_Object $1 not found, Linking may fai','l !'#000+
'09012_W_Library $1 not found, Linking may fail !'#000+
- '09013_E_Error while linking',#000+
+ '09013_E_Error while linking'#000+
'09014_E_Can'#039't call the linker, switching to external linking'#000+
'09015_I_Linking $1'#000+
'09016_E_Util $1 not found, switching to external linking'#000+
- '09017_T_Using util $1'#000+
+ '09017_T_Using util $1'#000,
'09018_E_Creation of Executables not supported'#000+
- '09019_E_Creation of Dynamic/Shared',' Libraries not supported'#000+
+ '09019_E_Creation of Dynamic/Shared Libraries not supported'#000+
'09035_E_Creation of Static Libraries not supported'#000+
'09020_I_Closing script $1'#000+
- '09021_E_Resource compiler "$1" not found, switching to external mode'#000+
+ '09021_E_Resource compiler "$1" not found, switching to ext','ernal mode'+
+ #000+
'09022_I_Compiling resource $1'#000+
- '09023_T_Unit $1 cannot be statically li','nked, switching to smart link'+
- 'ing'#000+
+ '09023_T_Unit $1 cannot be statically linked, switching to smart linkin'+
+ 'g'#000+
'09024_T_Unit $1 cannot be smart linked, switching to static linking'#000+
- '09025_T_Unit $1 cannot be shared linked, switching to static linking'#000+
+ '09025_T_Unit $1 cannot be shared linked, switching to stati','c linking'+
+ #000+
'09026_E_Unit $1 cannot be smart or static linked'#000+
- '09027_E_Unit $1 canno','t be shared or static linked'#000+
+ '09027_E_Unit $1 cannot be shared or static linked'#000+
'09028_D_Calling resource compiler "$1" with "$2" as command line'#000+
'09029_E_Error while compiling resources'#000+
- '09030_E_Can'#039't call the resource compiler "$1", switching to extern'+
- 'al mode'#000+
- '09031_E_Can'#039't open resource file',' "$1"'#000+
+ '09030_E_Can'#039't call the res','ource compiler "$1", switching to exte'+
+ 'rnal mode'#000+
+ '09031_E_Can'#039't open resource file "$1"'#000+
'09032_E_Can'#039't write resource file "$1"'#000+
'09033_N_File "$1" not found for backquoted cat command'#000+
- '09034_W_"$1" not found, this will probably cause a linking failure'#000+
+ '09034_W_"$1" not found, this will probably cause a linking f','ailure'#000+
'09128_F_Can'#039't post process executable $1'#000+
- '09129_F_Can'#039't open executable $1',#000+
+ '09129_F_Can'#039't open executable $1'#000+
'09130_X_Size of Code: $1 bytes'#000+
'09131_X_Size of initialized data: $1 bytes'#000+
'09132_X_Size of uninitialized data: $1 bytes'#000+
'09133_X_Stack space reserved: $1 bytes'#000+
- '09134_X_Stack space committed: $1 bytes'#000+
- '09200_F_Executable image size is too big ','for $1 target.'#000+
+ '0','9134_X_Stack space committed: $1 bytes'#000+
+ '09200_F_Executable image size is too big for $1 target.'#000+
'09201_W_Object file "$1" contains 32-bit absolute relocation to symbol'+
' "$2".'#000+
'09202_E_Program segment too large (exceeds 64k by $1 bytes)'#000+
- '09203_E_Code segment "$1" too large (exceeds 64k by $2 bytes)'#000+
- '09204_E_Data segment "$1" ','too large (exceeds 64k by $2 bytes)'#000+
+ '09203_E_','Code segment "$1" too large (exceeds 64k by $2 bytes)'#000+
+ '09204_E_Data segment "$1" too large (exceeds 64k by $2 bytes)'#000+
'09205_E_Segment "$1" too large (exceeds 64k by $2 bytes)'#000+
'09206_E_Group "$1" too large (exceeds 64k by $2 bytes)'#000+
- '09207_E_Cannot create a .COM file, because the program contains segmen'+
- 't relocations'#000+
- '09208_W_','Program "$1" uses experimental CheckPointer option'#000+
+ '09207_E_Cann','ot create a .COM file, because the program contains segm'+
+ 'ent relocations'#000+
+ '09208_W_Program "$1" uses experimental CheckPointer option'#000+
'09209_E_Multiple defined symbol "$1"'#000+
'09210_E_COMDAT selection mode $1 not supported (section: "$1")'#000+
- '09211_E_Associative section expected for COMDAT section "$1"'#000+
- '09212_E_COMDAT section selec','tion mode doesn'#039't match for section '+
- '"$1" and symbol "$2"'#000+
+ '09211_E_A','ssociative section expected for COMDAT section "$1"'#000+
+ '09212_E_COMDAT section selection mode doesn'#039't match for section "$'+
+ '1" and symbol "$2"'#000+
'09213_E_Associative COMDAT section for section "$1" not found'#000+
- '09214_D_Discarding duplicate symbol "$1" due to COMDAT selection mode'#000+
- '09215_D_Discarding duplicate symbol "$1" with same ','size due to COMDA'+
- 'T selection mode'#000+
+ '09214_D_Discarding duplicate symbol "$1" ','due to COMDAT selection mod'+
+ 'e'#000+
+ '09215_D_Discarding duplicate symbol "$1" with same size due to COMDAT '+
+ 'selection mode'#000+
'09216_D_Discarding duplicate symbol "$1" with same content due to COMD'+
'AT selection mode'#000+
- '09217_D_Replacing duplicate symbol "$1" with smaller size due to COMDA'+
- 'T selection mode'#000+
- '09218_E_Size of duplicate COMDA','T symbol "$1" differs'#000+
+ '09217_D_Replacing duplicate symbol "$1','" with smaller size due to COM'+
+ 'DAT selection mode'#000+
+ '09218_E_Size of duplicate COMDAT symbol "$1" differs'#000+
'09219_E_Content of duplicate COMDAT symbol "$1" differs'#000+
'09220_E_COMDAT selection mode for symbol "$1" differs'#000+
- '09221_E_Undefined symbol: $1 (first seen in $2)'#000+
+ '09221_E_Undefined symbol: $1',' (first seen in $2)'#000+
'09222_E_Undefined symbol: $1'#000+
'10000_T_Unitsearch: $1'#000+
- '10001_T_','PPU Loading $1'#000+
+ '10001_T_PPU Loading $1'#000+
'10002_U_PPU Name: $1'#000+
'10003_U_PPU Flags: $1'#000+
'10004_U_PPU Crc: $1'#000+
'10005_U_PPU Time: $1'#000+
'10006_U_PPU File too short'#000+
- '10007_U_PPU Invalid Header (no PPU at the begin)'#000+
+ '10007_U_PPU Invalid Header (no PPU',' at the begin)'#000+
'10008_U_PPU Invalid Version $1'#000+
- '10009_U_PPU is compiled for anothe','r processor'#000+
+ '10009_U_PPU is compiled for another processor'#000+
'10010_U_PPU is compiled for another target'#000+
'10011_U_PPU Source: $1'#000+
'10012_U_Writing $1'#000+
'10013_F_Can'#039't Write PPU-File'#000+
'10014_F_Error reading PPU-File'#000+
- '10015_F_Unexpected end of PPU-File'#000+
+ '100','15_F_Unexpected end of PPU-File'#000+
'10016_F_Invalid PPU-File entry: $1'#000+
- '10017_F_PPU D','bx count problem'#000+
+ '10017_F_PPU Dbx count problem'#000+
'10018_E_Illegal unit name: $1 (expecting $2)'#000+
'10019_F_Too much units'#000+
'10020_F_Circular unit reference between $1 and $2'#000+
- '10021_F_Can'#039't compile unit $1, no sources available'#000+
+ '10021_F_Can'#039't compile uni','t $1, no sources available'#000+
'10022_F_Can'#039't find unit $1 used by $2'#000+
- '10023_W_Unit $1',' was not found but $2 exists'#000+
+ '10023_W_Unit $1 was not found but $2 exists'#000+
'10024_F_Unit $1 searched but $2 found'#000+
'10025_W_Compiling the system unit requires the -Us switch'#000+
- '10026_F_There were $1 errors compiling module, stopping'#000+
+ '10026_F_There were $1 errors compil','ing module, stopping'#000+
'10027_U_Load from $1 ($2) unit $3'#000+
- '10028_U_Recompiling $1, c','hecksum changed for $2'#000+
+ '10028_U_Recompiling $1, checksum changed for $2'#000+
'10029_U_Recompiling $1, source found only'#000+
'10030_U_Recompiling unit, static lib is older than ppufile'#000+
- '10031_U_Recompiling unit, shared lib is older than ppufile'#000+
- '10032_U_Recompiling unit, obj and asm are older than ppuf','ile'#000+
+ '10031_U_Recompiling unit, shared lib',' is older than ppufile'#000+
+ '10032_U_Recompiling unit, obj and asm are older than ppufile'#000+
'10033_U_Recompiling unit, obj is older than asm'#000+
'10034_U_Parsing interface of $1'#000+
'10035_U_Parsing implementation of $1'#000+
'10036_U_Second load for unit $1'#000+
- '10037_U_PPU Check file $1 time $2'#000+
- '10040_W_Can'#039't recompile unit $1, but found modified i','nclude file'+
- 's'#000+
+ '10037_U','_PPU Check file $1 time $2'#000+
+ '10040_W_Can'#039't recompile unit $1, but found modified include files'#000+
'10041_U_File $1 is newer than the one used for creating PPU file $2'#000+
'10042_U_Trying to use a unit which was compiled with a different FPU m'+
'ode'#000+
- '10043_U_Loading interface units from $1'#000+
- '10044_U_Loading implementation units from $1'#000,
+ '10043','_U_Loading interface units from $1'#000+
+ '10044_U_Loading implementation units from $1'#000+
'10045_U_Interface CRC changed for unit $1'#000+
'10046_U_Implementation CRC changed for unit $1'#000+
'10047_U_Finished compiling unit $1'#000+
- '10048_U_Adding dependency: $1 depends on $2'#000+
+ '10048_U_Adding dependency: $1 depend','s on $2'#000+
'10049_U_No reload, is caller: $1'#000+
- '10050_U_No reload, already in second co','mpile: $1'#000+
+ '10050_U_No reload, already in second compile: $1'#000+
'10051_U_Flag for reload: $1'#000+
'10052_U_Forced reloading'#000+
'10053_U_Previous state of $1: $2'#000+
'10054_U_Already compiling $1, setting second compile'#000+
- '10055_U_Loading unit $1'#000+
+ '10055_U_Loa','ding unit $1'#000+
'10056_U_Finished loading unit $1'#000+
'10057_U_Registering new unit $1'#000+
- '10','058_U_Re-resolving unit $1'#000+
+ '10058_U_Re-resolving unit $1'#000+
'10059_U_Skipping re-resolving unit $1, still loading used units'#000+
'10060_U_Unloading resource unit $1 (not needed)'#000+
- '10061_E_Unit $1 was compiled using a different whole program optimizat'+
- 'ion feedback input ($2, $3); re','compile it without wpo or use the sam'+
+ '10061_E_Unit $1 was c','ompiled using a different whole program optimiz'+
+ 'ation feedback input ($2, $3); recompile it without wpo or use the sam'+
'e wpo feedback input file for this compilation invocation'#000+
- '10062_U_Indirect interface (objects/classes) CRC changed for unit $1'#000+
+ '10062_U_Indirect interface (objects/classes) CRC changed for unit',' $1'+
+ #000+
'10063_U_PPU is compiled for another i8086 memory model'#000+
- '10064_U_Loading unit ','$1 from package $2'#000+
+ '10064_U_Loading unit $1 from package $2'#000+
'10065_F_Internal type "$1" was not found. Check if you use the correct'+
' run time library.'#000+
- '10066_F_Internal type "$1" does not look as expected. Check if you use'+
- ' the correct run time library.'#000+
- '10067_U_Skipping unit, PPU and ','compiler have to be both compiled wit'+
- 'h or without LLVM support'#000+
+ '10066_F_Internal type "$1" does not look as expected','. Check if you u'+
+ 'se the correct run time library.'#000+
+ '10067_U_Skipping unit, PPU and compiler have to be both compiled with '+
+ 'or without LLVM support'#000+
'11000_O_$1 [options] <inputfile> [options]'#000+
- '11001_W_Only one source file supported, changing source file to compil'+
- 'e from "$1" into "$2"'#000+
- '11002_W_DEF file can be created only for O','S/2'#000+
+ '11001_W_Only one source file supported, changing sourc','e file to comp'+
+ 'ile from "$1" into "$2"'#000+
+ '11002_W_DEF file can be created only for OS/2'#000+
'11003_E_Nested response files are not supported'#000+
'11004_F_No source file name in command line'#000+
'11005_N_No option inside $1 config file'#000+
- '11006_E_Illegal parameter: $1'#000+
+ '11006_E_Illegal paramete','r: $1'#000+
'11007_H_-? writes help pages'#000+
'11008_F_Too many config files nested'#000+
- '11009_F_','Unable to open file $1'#000+
+ '11009_F_Unable to open file $1'#000+
'11010_D_Reading further options from $1'#000+
'11011_W_Target is already set to: $1'#000+
- '11012_W_Shared libs not supported on DOS platform, reverting to static'+
- #000+
- '11013_F_In options file $1 at line $2 too many #IF(N)DEFs encountered',
- #000+
+ '11012_W_Shared libs not supported on DOS platform, reverting',' to stat'+
+ 'ic'#000+
+ '11013_F_In options file $1 at line $2 too many #IF(N)DEFs encountered'#000+
'11014_F_In options file $1 at line $2 unexpected #ENDIFs encountered'#000+
'11015_F_Open conditional at the end of the options file'#000+
- '11016_W_Debug information generation is not supported by this executab'+
- 'le'#000+
+ '11016_W_Debug information generati','on is not supported by this execut'+
+ 'able'#000+
'11017_H_Try recompiling with -dGDB'#000+
- '11018_','W_You are using the obsolete switch $1'#000+
+ '11018_W_You are using the obsolete switch $1'#000+
'11019_W_You are using the obsolete switch $1, please use $2'#000+
- '11020_N_Switching assembler to default source writing assembler'#000+
+ '11020_N_Switching assembler to default source writing assembl','er'#000+
'11021_W_Assembler output selected "$1" is not compatible with "$2"'#000+
- '11022_W_"$','1" assembler use forced'#000+
+ '11022_W_"$1" assembler use forced'#000+
'11026_T_Reading options from file $1'#000+
'11027_T_Reading options from environment $1'#000+
'11028_D_Handling option "$1"'#000+
- '11029_O_*** press enter ***'#000+
+ '11029_O_*** press enter **','*'#000+
'11030_H_Start of reading config file $1'#000+
- '11031_H_End of reading config file $1'#000,
+ '11031_H_End of reading config file $1'#000+
'11032_D_Interpreting option "$1"'#000+
'11036_D_Interpreting firstpass option "$1"'#000+
'11033_D_Interpreting file option "$1"'#000+
'11034_D_Reading config file "$1"'#000+
- '11035_D_Found source file name "$1"'#000+
+ '11035_D_Found',' source file name "$1"'#000+
'11039_E_Unknown codepage "$1"'#000+
- '11040_F_Config file $1 is a',' directory'#000+
+ '11040_F_Config file $1 is a directory'#000+
'11041_W_Assembler output selected "$1" cannot generate debug info, deb'+
'ugging disabled'#000+
- '11042_W_Use of ppc386.cfg is deprecated, please use fpc.cfg instead'#000+
+ '11042_W_Use of ppc386.cfg is deprecated, please use fpc.cfg ins','tead'#000+
'11043_F_In options file $1 at line $2 #ELSE directive without #IF(N)DE'+
- 'F fou','nd'#000+
+ 'F found'#000+
'11044_F_Option "$1" is not, or not yet, supported on the current targe'+
't platform'#000+
'11045_F_The feature "$1" is not, or not yet, supported on the selected'+
- ' target platform'#000+
- '11046_N_DWARF debug information cannot be used with smart linking on ',
- 'this target, switching to static linking'#000+
+ ' targe','t platform'#000+
+ '11046_N_DWARF debug information cannot be used with smart linking on t'+
+ 'his target, switching to static linking'#000+
'11047_W_Option "$1" is ignored for the current target platform.'#000+
- '11048_W_Disabling external debug information because it is unsupported'+
- ' for the selected target/debug format combination.'#000+
- '11049_N_DWARF ','debug information cannot be used with smart linking wi'+
- 'th external assembler, disabling static library creation.'#000+
- '11050_E_Invalid value for MACOSX_DEPLOYMENT_TARGET environment variabl'+
- 'e: $1'#000+
- '11051_E_Invalid value for IPHONEOS_DEPLOYMENT_TARGET',' environment var'+
- 'iable: $1'#000+
- '11052_E_You must use a FPU type of VFPV2, VFPV3 or VFPV3_D16 when usin'+
- 'g the EABIHF ABI target'#000+
- '11053_W_The selected debug format is not supported on the current targ'+
- 'et, not changing the current setting'#000+
- '11054_E_Argum','ent to "$1" is missing'#000+
+ '11048_W_Disabling external debug information because it',' is unsupport'+
+ 'ed for the selected target/debug format combination.'#000+
+ '11049_N_DWARF debug information cannot be used with smart linking with'+
+ ' external assembler, disabling static library creation.'#000+
+ '11050_E_Invalid value for MACOSX_DEPLOYMENT_TARG','ET environment varia'+
+ 'ble: $1'#000+
+ '11051_E_Invalid value for IPHONEOS_DEPLOYMENT_TARGET environment varia'+
+ 'ble: $1'#000+
+ '11052_E_You must use one of the VFP FPU types when using the EABIHF AB'+
+ 'I target'#000+
+ '11053_W_The selected debug format is not supported on t','he current ta'+
+ 'rget, not changing the current setting'#000+
+ '11054_E_Argument to "$1" is missing'#000+
'11055_E_Malformed parameter: $1'#000+
'11056_W_Smart linking requires external linker'#000+
'11057_E_Creating .COM files is not supported in the current memory mod'+
- 'el. Only the tiny memory model supports making .COM files.'#000+
- '11058_W_E','xperimental CheckPointer option not enabled because it is i'+
- 'ncomptatible with -Ur option.'#000+
+ 'el.',' Only the tiny memory model supports making .COM files.'#000+
+ '11058_W_Experimental CheckPointer option not enabled because it is inc'+
+ 'omptatible with -Ur option.'#000+
'11059_E_Unsupported target architecture -P$1, invoke the "fpc" compile'+
- 'r driver instead.'#000+
- '11060_E_Feature switches are only supported while compiling the',' syst'+
- 'em unit.'#000+
+ 'r driver instead','.'#000+
+ '11060_E_Feature switches are only supported while compiling the system'+
+ ' unit.'#000+
'11061_N_The selected debug format is not supported by the internal lin'+
'ker, switching to external linking'#000+
- '11062_E_You can not use both options ($1) ($2) at same time.'#000+
- '12000_F_Cannot open whole program optimization feedback file',' "$1"'#000+
+ '11062_E_You can not use both options ($1) ($2) at same t','ime.'#000+
+ '12000_F_Cannot open whole program optimization feedback file "$1"'#000+
'12001_D_Processing whole program optimization information in wpo feedb'+
'ack file "$1"'#000+
'12002_D_Finished processing the whole program optimization information'+
- ' in wpo feedback file "$1"'#000+
- '12003_E_Expected section header, but got "$2" at line',' $1 of wpo feed'+
- 'back file'#000+
+ ' in wpo feedbac','k file "$1"'#000+
+ '12003_E_Expected section header, but got "$2" at line $1 of wpo feedba'+
+ 'ck file'#000+
'12004_W_No handler registered for whole program optimization section "'+
'$2" at line $1 of wpo feedback file, ignoring'#000+
- '12005_D_Found whole program optimization section "$1" with information'+
- ' about "$2"'#000+
- '12006_F_The selec','ted whole program optimizations require a previousl'+
- 'y generated feedback file (use -Fw to specify)'#000+
+ '12005_D_Found whole program optimi','zation section "$1" with informati'+
+ 'on about "$2"'#000+
+ '12006_F_The selected whole program optimizations require a previously '+
+ 'generated feedback file (use -Fw to specify)'#000+
'12007_E_No collected information necessary to perform "$1" whole progr'+
- 'am optimization found'#000+
- '12008_F_Specify a whole program optimization feedb','ack file to store '+
- 'the generated info in (using -FW)'#000+
+ 'am opti','mization found'#000+
+ '12008_F_Specify a whole program optimization feedback file to store th'+
+ 'e generated info in (using -FW)'#000+
'12009_E_Not generating any whole program optimization information, yet'+
' a feedback file was specified (using -FW)'#000+
- '12010_E_Not performing any whole program optimizations, yet an input f'+
- 'eedba','ck file was specified (using -Fw)'#000+
+ '12010_E_No','t performing any whole program optimizations, yet an input'+
+ ' feedback file was specified (using -Fw)'#000+
'12011_D_Skipping whole program optimization section "$1", because not '+
'needed by the requested optimizations'#000+
- '12012_W_Overriding previously read information for "$1" from feedback '+
- 'input file using information',' in section "$2"'#000+
+ '12012_W_Overriding previously rea','d information for "$1" from feedbac'+
+ 'k input file using information in section "$2"'#000+
'12013_E_Cannot extract symbol liveness information from program when s'+
'tripping symbols, use -Xs-'#000+
- '12014_E_Cannot extract symbol liveness information from program when w'+
- 'hen not linking'#000+
- '12015_F_Cannot find "$1" or "$2" to extr','act symbol liveness informat'+
- 'ion from linked program'#000+
+ '12014_E_Cannot extract symbol liveness information from progr','am when'+
+ ' when not linking'#000+
+ '12015_F_Cannot find "$1" or "$2" to extract symbol liveness informatio'+
+ 'n from linked program'#000+
'12016_E_Error during reading symbol liveness information produced by "'+
'$1"'#000+
- '12017_F_Error executing "$1" (exitcode: $2) to extract symbol informat'+
- 'ion from linked program'#000+
- '12018_E_Collection o','f symbol liveness information can only help when'+
- ' using smart linking, use -CX -XX'#000+
+ '12017_F_Error executing "$1" (exitcode: $2) to ex','tract symbol inform'+
+ 'ation from linked program'#000+
+ '12018_E_Collection of symbol liveness information can only help when u'+
+ 'sing smart linking, use -CX -XX'#000+
'12019_E_Cannot create specified whole program optimisation feedback fi'+
'le "$1"'#000+
- '13001_F_Can'#039't find package $1'#000+
+ '13001_F_Can'#039't f','ind package $1'#000+
'13002_U_PCP file for package $1 found'#000+
- '13003_E_Dupl','icate package $1'#000+
+ '13003_E_Duplicate package $1'#000+
'13004_E_Unit $1 can not be part of a package'#000+
'13005_N_Unit $1 is implicitely imported into package $2'#000+
'13006_F_Failed to create PCP file $2 for package $1'#000+
- '13007_F_Failed to read PCP file for package $1'#000+
- '13008_T_PCP loading $1'#000,
+ '13007','_F_Failed to read PCP file for package $1'#000+
+ '13008_T_PCP loading $1'#000+
'13009_U_PCP Name: $1'#000+
'13010_U_PCP Flags: $1'#000+
'13011_U_PCP Crc: $1'#000+
'13012_U_PCP Time: $1'#000+
'13013_U_PCP File too short'#000+
'13014_U_PCP Invalid Header (no PCP at the begin)'#000+
- '13015_U_PCP Invalid Version $1'#000+
+ '13015_U_PCP Inv','alid Version $1'#000+
'13016_U_PCP is compiled for another processor'#000+
- '130','17_U_PCP is compiled for another target'#000+
+ '13017_U_PCP is compiled for another target'#000+
'13018_U_Writing $1'#000+
'13019_F_Can'#039't Write PCP-File'#000+
'13020_F_Error reading PCP-File'#000+
'13021_F_Unexpected end of PCP-File'#000+
- '13022_F_Invalid PCP-File entry: $1'#000+
- '13023_U_Trying to use a unit which was compiled wit','h a different FPU'+
- ' mode'#000+
+ '13022_F_Invalid PCP-F','ile entry: $1'#000+
+ '13023_U_Trying to use a unit which was compiled with a different FPU m'+
+ 'ode'#000+
'13024_T_Packagesearch: $1'#000+
'13025_U_Required package $1'#000+
'13026_U_Contained unit $1'#000+
'13027_E_Unit $1 is already contained in package $2'#000+
- '13028_W_Unit $1 is imported from indirectly required package $2'#000+
- '13029_U_PPL filename $','1'#000+
+ '13028_W_Unit $1 is im','ported from indirectly required package $2'#000+
+ '13029_U_PPL filename $1'#000+
'11023_Free Pascal Compiler version $FPCFULLVERSION [$FPCDATE] for $FPC'+
'CPU'#010+
- 'Copyright (c) 1993-2020 by Florian Klaempfl and others'#000+
- '11024_Free Pascal Compiler version $FPCVERSION'#010+
+ 'Copyright (c) 1993-2021 by Florian Klaempfl and others'#000+
+ '11024_Free Pascal Compiler version $FPCVERSI','ON'#010+
#010+
'Compiler date : $FPCDATE'#010+
'Compiler CPU target: $FPCCPU'#010+
#010+
- 'S','upported targets (targets marked with '#039'{*}'#039' are under devel'+
- 'opment):'#010+
+ 'Supported targets (targets marked with '#039'{*}'#039' are under develop'+
+ 'ment):'#010+
' $OSTARGETS'#010+
#010+
'Supported CPU instruction sets:'#010+
' $INSTRUCTIONSETS'#010+
#010+
'Supported FPU instruction sets:'#010+
- ' $FPUINSTRUCTIONSETS'#010+
+ ' $FPUINS','TRUCTIONSETS'#010+
#010+
'Supported inline assembler modes:'#010+
' $ASMMODES'#010+
#010+
- 'Reco','gnized compiler and RTL features:'#010+
+ 'Recognized compiler and RTL features:'#010+
' $FEATURELIST'#010+
#010+
'Recognized modeswitches:'#010+
@@ -1427,364 +1430,364 @@ const msgtxt : array[0..000362,1..240] of char=(
'Supported Optimizations:'#010+
' $OPTIMIZATIONS'#010+
#010+
- 'Supported Whole Program Optimizations:'#010+
+ 'Su','pported Whole Program Optimizations:'#010+
' All'#010+
' $WPOPTIMIZATIONS'#010+
#010+
- 'Co','de Generation Backend'#010+
+ 'Code Generation Backend'#010+
' $CODEGENERATIONBACKEND'#010+
#010+
'Supported Microcontroller types:$\n $CONTROLLERTYPES$\n'#010+
'This program comes under the GNU General Public Licence'#010+
- 'For more information read COPYING.v2'#010+
+ 'For more infor','mation read COPYING.v2'#010+
#010+
- 'Please report bugs in our bug tracker on:',#010+
+ 'Please report bugs in our bug tracker on:'#010+
' https://bugs.freepascal.org'#010+
#010+
'More information may be found on our WWW pages (including directions'#010+
- 'for mailing lists useful for asking questions or discussing potential'#010+
+ 'for mailing lists useful for asking questions or discussing',' potentia'+
+ 'l'#010+
'new features, etc.):'#010+
- ' https://www.free','pascal.org'#000+
+ ' https://www.freepascal.org'#000+
'11025_F*0*_Only options valid for the default or selected platform are'+
' listed.'#010+
'**0*_Put + after a boolean switch option to enable it, - to disable it'+
'.'#010+
- '**1@<x>_Read compiler options from <x> in addition to the default fpc.'+
- 'cfg'#010+
- '**1a','_The compiler does not delete the generated assembler file'#010+
+ '**1@<x>_Read ','compiler options from <x> in addition to the default fp'+
+ 'c.cfg'#010+
+ '**1a_The compiler does not delete the generated assembler file'#010+
'**2a5_Don'#039't generate Big Obj COFF files for GNU Binutils older tha'+
'n 2.25 (Windows, NativeNT)'#010+
- '**2al_List sourcecode lines in assembler file'#010+
- '**2an_List node info in assembler file (-d','EXTDEBUG compiler)'#010+
+ '**2al_List sourcecode l','ines in assembler file'#010+
+ '**2an_List node info in assembler file (-dEXTDEBUG compiler)'#010+
'**2ao_Add an extra option to external assembler call (ignored for inte'+
'rnal)'#010+
'*L2ap_Use pipes instead of creating temporary assembler files'#010+
- '**2ar_List register allocation/release info in assembler file'#010+
- '**2at_List temp alloc','ation/release info in assembler file'#010+
+ '**2ar_List registe','r allocation/release info in assembler file'#010+
+ '**2at_List temp allocation/release info in assembler file'#010+
'**1A<x>_Output format:'#010+
'**2Adefault_Use default assembler'#010+
'3*2Aas_Assemble using GNU AS'#010+
'3*2Aas-darwin_Assemble Darwin Mach-O using GNU GAS'#010+
- '3*2Amacho_Mach-O (Darwin, Intel 32 bit) using internal writer'#010+
- '8*2A','nasm_Assemble using Nasm'#010+
+ '3','*2Amacho_Mach-O (Darwin, Intel 32 bit) using internal writer'#010+
+ '8*2Anasm_Assemble using Nasm'#010+
'8*2Anasmobj_Assemble using Nasm'#010+
'3*2Anasm_Assemble using Nasm'#010+
'3*2Anasmcoff_COFF (Go32v2) file using Nasm'#010+
'3*2Anasmelf_ELF32 (Linux) file using Nasm'#010+
- '3*2Anasmwin32_Win32 object file using Nasm'#010+
- '3*2Anasmwdosx_Win32/WDOSX ','object file using Nasm'#010+
+ '3*2A','nasmwin32_Win32 object file using Nasm'#010+
+ '3*2Anasmwdosx_Win32/WDOSX object file using Nasm'#010+
'3*2Anasmdarwin_macho32 object file using Nasm (experimental)'#010+
'3*2Awasm_Obj file using Wasm (Watcom)'#010+
'3*2Anasmobj_Obj file using Nasm'#010+
- '3*2Amasm_Obj file using Masm (Microsoft)'#010+
+ '3*2Amasm_Obj file usi','ng Masm (Microsoft)'#010+
'3*2Atasm_Obj file using Tasm (Borland)'#010+
- '3*2Ael','f_ELF (Linux) using internal writer'#010+
+ '3*2Aelf_ELF (Linux) using internal writer'#010+
'3*2Acoff_COFF (Go32v2) using internal writer'#010+
'3*2Apecoff_PE-COFF (Win32) using internal writer'#010+
'3*2Ayasm_Assemble using Yasm (experimental)'#010+
- '4*2Aas_Assemble using GNU AS'#010+
+ '4','*2Aas_Assemble using GNU AS'#010+
'4*2Agas_Assemble using GNU GAS'#010+
- '4*2Aas','-darwin_Assemble Darwin Mach-O using GNU GAS'#010+
+ '4*2Aas-darwin_Assemble Darwin Mach-O using GNU GAS'#010+
'4*2Amasm_Win64 object file using ml64 (Microsoft)'#010+
'4*2Apecoff_PE-COFF (Win64) using internal writer'#010+
- '4*2Aelf_ELF (Linux-64bit) using internal writer'#010+
+ '4*2Aelf_ELF (Linux-64bit) using',' internal writer'#010+
'4*2Ayasm_Assemble using Yasm (experimental)'#010+
- '4*2A','nasm_Assemble using Nasm (experimental)'#010+
+ '4*2Anasm_Assemble using Nasm (experimental)'#010+
'4*2Anasmwin64_Assemble Win64 object file using Nasm (experimental)'#010+
- '4*2Anasmelf_Assemble Linux-64bit object file using Nasm (experimental)'+
- #010+
- '4*2Anasmdarwin_Assemble darwin macho64 object file using Nasm ','(exper'+
- 'imental)'#010+
+ '4*2Anasmelf_Assemble Linux-64bit object file using Nasm (experimenta','l'+
+ ')'#010+
+ '4*2Anasmdarwin_Assemble darwin macho64 object file using Nasm (experim'+
+ 'ental)'#010+
'6*2Aas_Unix o-file using GNU AS'#010+
'6*2Agas_GNU Motorola assembler'#010+
'6*2Amit_MIT Syntax (old GAS)'#010+
'6*2Amot_Standard Motorola assembler'#010+
'6*2Avasm_Use vasm to assemble'#010+
- 'A*2Aas_Assemble using GNU AS'#010+
+ 'A*','2Aas_Assemble using GNU AS'#010+
'P*2Aas_Assemble using GNU AS'#010+
- 'S*2Aas_As','semble using GNU AS'#010+
+ 'S*2Aas_Assemble using GNU AS'#010+
'Z*2Asdcc-sdasz80_Assemble using SDCC-SDASZ80'#010+
'Z*2Az80asm_Assemble using z80asm'#010+
'**1b_Generate browser info'#010+
'**2bl_Generate local symbol info'#010+
- '**1B_Build all modules'#010+
+ '**1B_Build all mo','dules'#010+
'**1C<x>_Code generation options:'#010+
- '**2C3_Turn on ieee error c','hecking for constants'#010+
+ '**2C3_Turn on ieee error checking for constants'#010+
'**2Ca<x>_Select ABI; see fpc -i or fpc -ia for possible values'#010+
'**2Cb_Generate code for a big-endian variant of the target architectur'+
'e'#010+
- '**2Cc<x>_Set default calling convention to <x>'#010+
- '**2CD_Create also dynamic library (n','ot supported)'#010+
+ '**2Cc<x>_Set defau','lt calling convention to <x>'#010+
+ '**2CD_Create also dynamic library (not supported)'#010+
'**2Ce_Compilation with emulated floating point opcodes'#010+
'**2CE_Generate FPU code which can raise exceptions'#010+
- '**2Cf<x>_Select fpu instruction set to use; see fpc -i or fpc -if for '+
- 'possible values'#010+
- '**2CF<x>_Minimal floating point co','nstant precision (default, 32, 64)'+
- #010+
+ '**2Cf<x>_Select fpu instruction set to use; see fpc -i ','or fpc -if fo'+
+ 'r possible values'#010+
+ '**2CF<x>_Minimal floating point constant precision (default, 32, 64)'#010+
'**2Cg_Generate PIC code'#010+
'**2Ch<n>[,m]_<n> bytes min heap size (between 1023 and 67107840) and o'+
'ptionally [m] max heap size'#010+
- '**2Ci_IO-checking'#010+
+ '**2Ci_IO-checking'#010,
'A*2CI<x>_Select instruction set on ARM: ARM or THUMB'#010+
- 'L*2Cl<x>_LLV','M code generation options'#010+
+ 'L*2Cl<x>_LLVM code generation options'#010+
'L*3Clflto_Enable Link-time optimisation (needed both when compiling un'+
'its and programs/libraries)'#010+
- 'L*3Clfltonosystem_Disable LTO for the system unit (needed with at leas'+
- 't Xcode 10.2 and earlier due to linker bugs)'#010+
- 'L','*3Clv<x>_LLVM target version: Xcode-10.1, 7.0, 8.0, .., 10.0'#010+
+ 'L*3Clfltonosystem_Disable LTO for the system unit (','needed with at le'+
+ 'ast Xcode 10.2 and earlier due to linker bugs)'#010+
+ 'L*3Clv<x>_LLVM target version: Xcode-10.1, 7.0, 8.0, .., 10.0'#010+
'**2Cn_Omit linking stage'#010+
'P*2CN_Generate nil-pointer checks (AIX-only)'#010+
'**2Co_Check overflow of integer operations'#010+
- '**2CO_Check for possible overflow of integer operations'#010+
- '**2Cp<x>_S','elect instruction set; see fpc -i or fpc -ic for possible '+
- 'values'#010+
+ '*','*2CO_Check for possible overflow of integer operations'#010+
+ '**2Cp<x>_Select instruction set; see fpc -i or fpc -ic for possible va'+
+ 'lues'#010+
'**2CP<x>=<y>_ packing settings'#010+
'**3CPPACKSET=<y>_ <y> set allocation: 0, 1 or DEFAULT or NORMAL, 2, 4 '+
'and 8'#010+
- '**3CPPACKENUM=<y>_ <y> enum packing: 0, 1, 2 and 4 or DEFAULT or NOR','M'+
- 'AL'#010+
+ '**3','CPPACKENUM=<y>_ <y> enum packing: 0, 1, 2 and 4 or DEFAULT or NOR'+
+ 'MAL'#010+
'**3CPPACKRECORD=<y>_ <y> record packing: 0 or DEFAULT or NORMAL, 1, 2,'+
' 4, 8, 16 and 32'#010+
'**2Cr_Range checking'#010+
'**2CR_Verify object method call validity'#010+
- '**2Cs<n>_Set stack checking size to <n>'#010+
- '**2Ct_Stack checking (for testing only, see man','ual)'#010+
+ '**2Cs<n>_Set stack che','cking size to <n>'#010+
+ '**2Ct_Stack checking (for testing only, see manual)'#010+
'8*2CT<x>_Target-specific code generation options'#010+
'3*2CT<x>_Target-specific code generation options'#010+
'4*2CT<x>_Target-specific code generation options'#010+
- 'p*2CT<x>_Target-specific code generation options'#010+
- 'P*2CT<x>_Target-specific code generatio','n options'#010+
+ 'p*2CT<x>_Target-specifi','c code generation options'#010+
+ 'P*2CT<x>_Target-specific code generation options'#010+
'J*2CT<x>_Target-specific code generation options'#010+
'A*2CT<x>_Target-specific code generation options'#010+
- 'p*3CTsmalltoc_ Generate smaller TOCs at the expense of execution speed'+
- ' (AIX)'#010+
- 'P*3CTsmalltoc_ Generate smaller TOCs at the expense of ','execution spe'+
+ 'p*3CTsmalltoc_ Generate smaller TOCs at the expense of execution sp','e'+
'ed (AIX)'#010+
+ 'P*3CTsmalltoc_ Generate smaller TOCs at the expense of execution speed'+
+ ' (AIX)'#010+
'J*3CTautogetterprefix=X_ Automatically create getters for properties '+
'with prefix X (empty string disables)'#010+
- 'J*3CTautosetterprefix=X_ Automatically create setters for properties '+
- 'with prefix X (empty string disables)'#010+
- '8*','3CTcld_ Emit a CLD instruction before using the x8'+
- '6 string instructions'#010+
+ 'J*3CTautosetterprefix=X_ Automatically creat','e setters for propertie'+
+ 's with prefix X (empty string disables)'#010+
+ '8*3CTcld_ Emit a CLD instruction before using the x86 '+
+ 'string instructions'#010+
'3*3CTcld_ Emit a CLD instruction before using the x86 '+
+ 'string instructio','ns'#010+
+ '4*3CTcld_ Emit a CLD instruction before using the x86 '+
'string instructions'#010+
- '4*3CTcld_ Emit a CLD instruction before using ','the x8'+
- '6 string instructions'#010+
'8*3CTfarprocspushoddbp_ Increment BP before pushing it in the pr'+
'ologue of far functions'#010+
- 'J*3CTcompactintarrayinit_ Generate smaller (but potentially slower) co'+
- 'de for initializing integer array constants'#010+
- 'J*3C','Tenumfieldinit_ Initialize enumeration fields in construct'+
- 'ors to enumtype(0), after calling inherited constructors'#010+
- 'J*3CTinitlocals_ Initialize local variables that trigger a JV'+
- 'M bytecode verification error if used uninitializ','ed (slows down code'+
+ 'J*3CTcompactintarrayinit_ Generate smaller (but poten','tially slower) '+
+ 'code for initializing integer array constants'#010+
+ 'J*3CTenumfieldinit_ Initialize enumeration fields in constructor'+
+ 's to enumtype(0), after calling inherited constructors'#010+
+ 'J*3CTinitlocals_ Initialize local variables t','hat trigger a '+
+ 'JVM bytecode verification error if used uninitialized (slows down code'+
')'#010+
'J*3CTlowercaseprocstart_ Lowercase the first character of procedure/f'+
'unction/method names'#010+
- 'A*3CTthumbinterworking_ Generate Thumb interworking-safe code if possi'+
- 'ble'#010+
+ 'A*3CTthumbinterworking_ Generate Thumb interworking-safe code i','f pos'+
+ 'sible'#010+
'J*2Cv_Var/out parameter copy-out checking'#010+
- 'A*2CV<x>_Set',' section threadvar model to <x>'#010+
+ 'A*2CV<x>_Set section threadvar model to <x>'#010+
'**2CX_Create also smartlinked library'#010+
'**1d<x>_Defines the symbol <x>'#010+
'**1D_Generate a DEF file'#010+
- '**2DD<x>_Set the date string returned by %DATE% to x, it is not checke'+
- 'd for being a valid date string'#010+
- '**2Dd<x>_Set',' description to <x>'#010+
+ '**2DD<x>_Set the date string returned by %DATE% t','o x, it is not chec'+
+ 'ked for being a valid date string'#010+
+ '**2Dd<x>_Set description to <x>'#010+
'**2DT<x>_Set the time string returned by %TIME% to x, it is not checke'+
'd for being a valid time string'#010+
'**2Dv<x>_Set DLL version to <x>'#010+
- '*O2Dw_PM application'#010+
+ '*O2Dw_PM application'#010,
'**1e<x>_Set path to executable'#010+
'**1E_Same as -Cn'#010+
- '**1fPIC_Same as -','Cg'#010+
+ '**1fPIC_Same as -Cg'#010+
'**1F<x>_Set file names and paths:'#010+
'**2Fa<x>[,y]_(for a program) load units <x> and [y] before uses is par'+
'sed'#010+
'**2Fc<x>_Set input codepage to <x>'#010+
- '**2FC<x>_Set RC compiler binary name to <x>'#010+
- '**2Fd_Disable the compiler'#039's internal directory ca','che'#010+
+ '**2FC<x>_Set RC compiler bina','ry name to <x>'#010+
+ '**2Fd_Disable the compiler'#039's internal directory cache'#010+
'**2FD<x>_Set the directory where to search for compiler utilities'#010+
'**2Fe<x>_Redirect error output to <x>'#010+
'**2FE<x>_Set exe/unit output path to <x>'#010+
- '**2Ff<x>_Add <x> to framework path (Darwin only), or set IDF path to <'+
- 'x> (Xtensa-FreeRTOS)'#010,
+ '**2Ff<x>_Add <x> to framew','ork path (Darwin only), or set IDF path to'+
+ ' <x> (Xtensa-FreeRTOS)'#010+
'**2FF_Use fpcres as RC to RES compiler instead of windres or gorc'#010+
'**2Fi<x>_Add <x> to include path'#010+
'**2Fl<x>_Add <x> to library path'#010+
'**2FL<x>_Use <x> as dynamic linker'#010+
- '**2Fm<x>_Load unicode conversion table from <x>.txt in the compiler di'+
- 'r'#010+
- '*','*2FM<x>_Set the directory where to search for unicode binary files'#010+
+ '**2Fm<x>','_Load unicode conversion table from <x>.txt in the compiler '+
+ 'dir'#010+
+ '**2FM<x>_Set the directory where to search for unicode binary files'#010+
'**2FN<x>_Add <x> to list of default unit scopes (namespaces)'#010+
'**2Fo<x>_Add <x> to object path'#010+
- '**2Fr<x>_Load error message file <x>'#010+
- '**2FR<x>_Set resource (.res) linker to <x>'#010,
+ '**2Fr<x>_Load e','rror message file <x>'#010+
+ '**2FR<x>_Set resource (.res) linker to <x>'#010+
'**2Fu<x>_Add <x> to unit path'#010+
'**2FU<x>_Set unit output path to <x>, overrides -FE'#010+
'**2FW<x>_Store generated whole-program optimization feedback in <x>'#010+
- '**2Fw<x>_Load previously stored whole-program optimization feedback fr'+
- 'om <x>'#010+
- '*g1g_Generate',' debug information (default format for target)'#010+
+ '**2Fw<x>_Load previously ','stored whole-program optimization feedback '+
+ 'from <x>'#010+
+ '*g1g_Generate debug information (default format for target)'#010+
'*g2gc_Generate checks for pointers (experimental, only available on so'+
'me targets, might generate false positive)'#010+
- '*g2gh_Use heaptrace unit (for memory leak/corruption debugging)'#010+
- '*g2gl_Use line i','nfo unit (show more info with backtraces)'#010+
+ '*g2gh_Use heapt','race unit (for memory leak/corruption debugging)'#010+
+ '*g2gl_Use line info unit (show more info with backtraces)'#010+
'*g2gm_Generate Microsoft CodeView debug information (experimental)'#010+
'*g2go<x>_Set debug information options'#010+
- '*g3godwarfsets_ Enable DWARF '#039'set'#039' type debug information (bre'+
- 'aks gdb < 6.5)'#010+
- '*g3gostabsabsin','cludes_ Store absolute/full include file paths in Sta'+
- 'bs'#010+
+ '*g3godwarfsets_ Enable DWAR','F '#039'set'#039' type debug information (b'+
+ 'reaks gdb < 6.5)'#010+
+ '*g3gostabsabsincludes_ Store absolute/full include file paths in Stabs'+
+ #010+
'*g3godwarfmethodclassprefix_ Prefix method names in DWARF with class n'+
'ame'#010+
- '*g3godwarfcpp_ Simulate C++ debug information in DWARF'#010+
- '*g3godwarfomflinnum_ Generate line number information i','n OMF LINNUM '+
- 'records in MS LINK format in addition to the DWARF debug information ('+
- 'Open Watcom Debugger/Linker compatibility)'#010+
+ '*g3godwarfcpp_ Simulate C++ debug information',' in DWARF'#010+
+ '*g3godwarfomflinnum_ Generate line number information in OMF LINNUM re'+
+ 'cords in MS LINK format in addition to the DWARF debug information (Op'+
+ 'en Watcom Debugger/Linker compatibility)'#010+
'*g2gp_Preserve case in stabs symbol names'#010+
- '*g2gs_Generate Stabs debug information'#010+
- '*g2gt_Trash local variables (to d','etect uninitialized uses; multiple '+
- #039't'#039' changes the trashing value)'#010+
+ '*g2gs_G','enerate Stabs debug information'#010+
+ '*g2gt_Trash local variables (to detect uninitialized uses; multiple '#039+
+ 't'#039' changes the trashing value)'#010+
'*g2gv_Generates programs traceable with Valgrind'#010+
'*g2gw_Generate DWARFv2 debug information (same as -gw2)'#010+
- '*g2gw2_Generate DWARFv2 debug information'#010+
- '*g2gw3_Generate DWARFv3 de','bug information'#010+
+ '*g2','gw2_Generate DWARFv2 debug information'#010+
+ '*g2gw3_Generate DWARFv3 debug information'#010+
'*g2gw4_Generate DWARFv4 debug information (experimental)'#010+
'**1i_Information'#010+
'**2iD_Return compiler date'#010+
'**2iSO_Return compiler OS'#010+
- '**2iSP_Return compiler host processor'#010+
+ '**2iSP_Return compiler host proc','essor'#010+
'**2iTO_Return target OS'#010+
'**2iTP_Return target processor'#010+
- '**2i','V_Return short compiler version'#010+
+ '**2iV_Return short compiler version'#010+
'**2iW_Return full compiler version'#010+
'**2ia_Return list of supported ABI targets'#010+
'**2ib_Return the used code generation backend type'#010+
- '**2ic_Return list of supported CPU instruction sets'#010+
- '**2if_Return list of suppor','ted FPU instruction sets'#010+
+ '**2ic_Return l','ist of supported CPU instruction sets'#010+
+ '**2if_Return list of supported FPU instruction sets'#010+
'**2ii_Return list of supported inline assembler modes'#010+
'**2im_Return list of supported modeswitches'#010+
'**2io_Return list of supported optimizations'#010+
- '**2ir_Return list of recognized compiler and RTL features'#010+
- '**2it_Return l','ist of supported targets'#010+
+ '**2ir_R','eturn list of recognized compiler and RTL features'#010+
+ '**2it_Return list of supported targets'#010+
'**2iu_Return list of supported microcontroller types'#010+
'**2iw_Return list of supported whole program optimizations'#010+
'**1I<x>_Add <x> to include path'#010+
- '**1k<x>_Pass <x> to the linker'#010+
+ '**1k<x','>_Pass <x> to the linker'#010+
'**1l_Write logo'#010+
- '**1M<x>_Set language mod','e to <x> / enable modeswitch <x> (see option'+
- ' -im)'#010+
+ '**1M<x>_Set language mode to <x> / enable modeswitch <x> (see option -'+
+ 'im)'#010+
'**2Mfpc_Free Pascal dialect (default)'#010+
'**2Mobjfpc_FPC mode with Object Pascal support'#010+
'**2Mdelphi_Delphi 7 compatibility mode'#010+
- '**2Mtp_TP/BP 7.0 compatibility mode'#010+
- '**2Mmacpas_Macintosh Pascal di','alects compatibility mode'#010+
+ '*','*2Mtp_TP/BP 7.0 compatibility mode'#010+
+ '**2Mmacpas_Macintosh Pascal dialects compatibility mode'#010+
'**2Miso_ISO 7185 mode'#010+
'**2Mextendedpascal_ISO 10206 mode'#010+
'**2Mdelphiunicode_Delphi 2009 and later compatibility mode'#010+
- '**2*_Each mode (as listed above) enables its default set of modeswitch'+
- 'es.'#010+
- '**2*_Other modeswitches a','re disabled and need to be enabled one by a'+
- 'nother.'#010+
+ '**2*_Each mode (as listed above) e','nables its default set of modeswit'+
+ 'ches.'#010+
+ '**2*_Other modeswitches are disabled and need to be enabled one by ano'+
+ 'ther.'#010+
'**1M<x>-_Disable modeswitch <x> (see option -im)'#010+
'**1n_Do not read the default config files'#010+
- '**1o<x>_Change the name of the executable produced to <x>'#010+
+ '**1o<x>_Change the name of the ex','ecutable produced to <x>'#010+
'**1O<x>_Optimizations:'#010+
- '**2O-_Disable opt','imizations'#010+
+ '**2O-_Disable optimizations'#010+
'**2O1_Level 1 optimizations (quick and debugger friendly)'#010+
'**2O2_Level 2 optimizations (-O1 + quick optimizations)'#010+
- '**2O3_Level 3 optimizations (-O2 + slow optimizations)'#010+
- '**2O4_Level 4 optimizations (-O3 + optimizations which might',' have un'+
- 'expected side effects)'#010+
+ '**2O3_Level 3 optimizations (-O2 + slow optimizati','ons)'#010+
+ '**2O4_Level 4 optimizations (-O3 + optimizations which might have unex'+
+ 'pected side effects)'#010+
'**2Oa<x>=<y>_Set alignment'#010+
'**2Oo[NO]<x>_Enable or disable optimizations; see fpc -i or fpc -io fo'+
'r possible values'#010+
- '**2Op<x>_Set target cpu for optimizing; see fpc -i or fpc -ic for poss'+
- 'ible values'#010+
- '**2OW<x>_Gen','erate whole-program optimization feedback for optimizati'+
- 'on <x>; see fpc -i or fpc -iw for possible values'#010+
- '**2Ow<x>_Perform whole-program optimization <x>; see fpc -i or fpc -iw'+
- ' for possible values'#010+
+ '**2Op<x>_Set target cpu for o','ptimizing; see fpc -i or fpc -ic for po'+
+ 'ssible values'#010+
+ '**2OW<x>_Generate whole-program optimization feedback for optimization'+
+ ' <x>; see fpc -i or fpc -iw for possible values'#010+
+ '**2Ow<x>_Perform whole-program optimization <x>; see fpc -i or fpc -i',
+ 'w for possible values'#010+
'**2Os_Optimize for size rather than speed'#010+
- '*','*1pg_Generate profile code for gprof (defines FPC_PROFILE)'#010+
+ '**1pg_Generate profile code for gprof (defines FPC_PROFILE)'#010+
'F*1P<x>_Target CPU / compiler related options:'#010+
'F*2PB_Show default compiler binary'#010+
'F*2PP_Show default target cpu'#010+
- 'F*2P<x>_Set target CPU (aarch64,arm,avr,i386,i8086,jvm,m68k,mips,mips',
- 'el,powerpc,powerpc64,sparc,x86_64)'#010+
+ 'F*2P','<x>_Set target CPU (aarch64,arm,avr,i386,i8086,jvm,m68k,mips,mip'+
+ 'sel,powerpc,powerpc64,sparc,x86_64)'#010+
'**1R<x>_Assembler reading style:'#010+
'**2Rdefault_Use default assembler for target'#010+
'3*2Ratt_Read AT&T style assembler'#010+
- '3*2Rintel_Read Intel style assembler'#010+
+ '3*2Rintel_Read Intel style a','ssembler'#010+
'4*2Ratt_Read AT&T style assembler'#010+
- '4*2Rintel_Read Intel s','tyle assembler'#010+
+ '4*2Rintel_Read Intel style assembler'#010+
'8*2Ratt_Read AT&T style assembler'#010+
'8*2Rintel_Read Intel style assembler'#010+
'6*2RMOT_Read Motorola style assembler'#010+
'**1S<x>_Syntax options:'#010+
'**2S2_Same as -Mobjfpc'#010+
- '**2Sc_Support operators like C (*=,+=,/= and -=)'#010+
- '**2Sa_Turn on assert','ions'#010+
+ '**2S','c_Support operators like C (*=,+=,/= and -=)'#010+
+ '**2Sa_Turn on assertions'#010+
'**2Sd_Same as -Mdelphi'#010+
'**2Se<x>_Error options. <x> is a combination of the following:'#010+
'**3*_<n> : Compiler halts after the <n> errors (default is 1)'#010+
- '**3*_w : Compiler also halts after warnings'#010+
+ '**3*_w : Compiler also',' halts after warnings'#010+
'**3*_n : Compiler also halts after notes'#010+
- '**','3*_h : Compiler also halts after hints'#010+
+ '**3*_h : Compiler also halts after hints'#010+
'**2Sf_Enable certain features in compiler and RTL; see fpc -i or fpc -'+
'ir for possible values)'#010+
- '**2Sg_Enable LABEL and GOTO (default in -Mtp and -Mdelphi)'#010+
- '**2Sh_Use reference counted strings (ansistring ','by default) instead '+
- 'of shortstrings'#010+
+ '**2Sg_Enable LABEL and GOTO (default in -M','tp and -Mdelphi)'#010+
+ '**2Sh_Use reference counted strings (ansistring by default) instead of'+
+ ' shortstrings'#010+
'**2Si_Turn on inlining of procedures/functions declared as "inline"'#010+
'**2Sj_Allows typed constants to be writeable (default in all modes)'#010+
- '**2Sk_Load fpcylix unit'#010+
+ '**2','Sk_Load fpcylix unit'#010+
'**2SI<x>_Set interface style to <x>'#010+
- '**3SIcom','_COM compatible interface (default)'#010+
+ '**3SIcom_COM compatible interface (default)'#010+
'**3SIcorba_CORBA compatible interface'#010+
'**2sT_Generate script only to link on target'#010+
'**2Sm_Support macros like C (global)'#010+
- '**2So_Same as -Mtp'#010+
+ '**2So_Same as -Mtp'#010,
'**2Sr_Transparent file names in ISO mode'#010+
- '**2Ss_Constructor name m','ust be init (destructor must be done)'#010+
+ '**2Ss_Constructor name must be init (destructor must be done)'#010+
'**2Sv_Support vector processing (use CPU vector extensions if availabl'+
'e)'#010+
- '**2Sx_Enable exception keywords (default in Delphi/ObjFPC modes)'#010+
+ '**2Sx_Enable exception keywords (default in Delphi/ObjFPC modes)',#010+
'**2Sy_@<pointer> returns a typed pointer, same as $T+'#010+
- '**1s_Do no','t call assembler and linker'#010+
+ '**1s_Do not call assembler and linker'#010+
'**2sh_Generate script to link on host'#010+
'**2st_Generate script to assemble and link on target'#010+
'**2sr_Skip register allocation phase (use with -alr)'#010+
- '**1T<x>_Target operating system:'#010+
+ '**1','T<x>_Target operating system:'#010+
'3*2Tandroid_Android'#010+
'3*2Taros_AROS'#010+
- '3','*2Tbeos_BeOS'#010+
+ '3*2Tbeos_BeOS'#010+
'3*2Tdarwin_Darwin/Mac OS X'#010+
'3*2Tembedded_Embedded'#010+
'3*2Temx_OS/2 via EMX (including EMX/RSX extender)'#010+
'3*2Tfreebsd_FreeBSD'#010+
- '3*2Tgo32v2_Version 2 of DJ Delorie DOS extender'#010+
+ '3*2Tgo32v2_Version 2 of DJ Delorie DOS exte','nder'#010+
'3*2Thaiku_Haiku'#010+
- '3*2Tiphonesim_iPhoneSimulator from iOS SDK 3','.2+ (older versions: -Td'+
- 'arwin)'#010+
+ '3*2Tiphonesim_iPhoneSimulator from iOS SDK 3.2+ (older versions: -Tdar'+
+ 'win)'#010+
'3*2Tlinux_Linux'#010+
'3*2Tnativent_Native NT API (experimental)'#010+
'3*2Tnetbsd_NetBSD'#010+
'3*2Tnetware_Novell Netware Module (clib)'#010+
- '3*2Tnetwlibc_Novell Netware Module (libc)'#010+
+ '3*2Tnetwlibc_Novell Netware',' Module (libc)'#010+
'3*2Topenbsd_OpenBSD'#010+
'3*2Tos2_OS/2 / eComStation'#010+
- '3*2','Tsymbian_Symbian OS'#010+
+ '3*2Tsymbian_Symbian OS'#010+
'3*2Tsolaris_Solaris'#010+
'3*2Twatcom_Watcom compatible DOS extender'#010+
'3*2Twdosx_WDOSX DOS extender'#010+
'3*2Twin32_Windows 32 Bit'#010+
'3*2Twince_Windows CE'#010+
- '4*2Tandroid_Android'#010+
+ '4*2Tandroid_Androi','d'#010+
'4*2Taros_AROS'#010+
'4*2Tdarwin_Darwin/Mac OS X'#010+
- '4*2Tdragonfly_DragonFl','y BSD'#010+
+ '4*2Tdragonfly_DragonFly BSD'#010+
'4*2Tembedded_Embedded'#010+
'4*2Tfreebsd_FreeBSD'#010+
'4*2Thaiku_Haiku'#010+
@@ -1793,19 +1796,19 @@ const msgtxt : array[0..000362,1..240] of char=(
'4*2Tnetbsd_NetBSD'#010+
'4*2Topenbsd_OpenBSD'#010+
'4*2Tsolaris_Solaris'#010+
- '4*2Twin64_Win64 (64 bit Windows systems)'#010+
+ '4*2Twin','64_Win64 (64 bit Windows systems)'#010+
'6*2Tamiga_Commodore Amiga'#010+
- '6*2Ta','tari_Atari ST/STe/TT'#010+
+ '6*2Tatari_Atari ST/STe/TT'#010+
'6*2Tembedded_Embedded'#010+
'6*2Tlinux_Linux'#010+
'6*2Tnetbsd_NetBSD'#010+
'6*2Tmacosclassic_Classic Mac OS'#010+
'6*2Tpalmos_PalmOS'#010+
'6*2Tsinclairql_Sinclair QL'#010+
- '8*2Tembedded_Embedded'#010+
+ '8*2Tembedded_Embedded',#010+
'8*2Tmsdos_MS-DOS (and compatible)'#010+
'8*2Twin16_Windows 16 Bit'#010+
- 'A*2Ta','ndroid_Android'#010+
+ 'A*2Tandroid_Android'#010+
'A*2Taros_AROS'#010+
'A*2Tembedded_Embedded'#010+
'A*2Tfreertos_FreeRTOS'#010+
@@ -1814,10 +1817,10 @@ const msgtxt : array[0..000362,1..240] of char=(
'A*2Tlinux_Linux'#010+
'A*2Tnds_Nintendo DS'#010+
'A*2Tnetbsd_NetBSD'#010+
- 'A*2Tpalmos_PalmOS'#010+
+ 'A*2Tpalmos_','PalmOS'#010+
'A*2Tsymbian_Symbian'#010+
'A*2Twince_Windows CE'#010+
- 'a*2Tandroid_Andro','id'#010+
+ 'a*2Tandroid_Android'#010+
'a*2Tdarwin_Darwin/Mac OS X'#010+
'a*2Tios_iOS'#010+
'a*2Tlinux_Linux'#010+
@@ -1827,11 +1830,11 @@ const msgtxt : array[0..000362,1..240] of char=(
'm*2Tandroid_Android'#010+
'm*2Tembedded_Embedded'#010+
'm*2Tlinux_Linux'#010+
- 'M*2Tembedded_Embedded'#010+
+ 'M*2T','embedded_Embedded'#010+
'M*2Tlinux_Linux'#010+
'P*2Taix_AIX'#010+
'P*2Tamiga_AmigaOS'#010+
- 'P','*2Tdarwin_Darwin/Mac OS X'#010+
+ 'P*2Tdarwin_Darwin/Mac OS X'#010+
'P*2Tembedded_Embedded'#010+
'P*2Tlinux_Linux'#010+
'P*2Tmacosclassic_Classic Mac OS'#010+
@@ -1839,11 +1842,11 @@ const msgtxt : array[0..000362,1..240] of char=(
'P*2Tnetbsd_NetBSD'#010+
'P*2Twii_Wii'#010+
'p*2Taix_AIX'#010+
- 'p*2Tdarwin_Darwin/Mac OS X'#010+
+ 'p*2Tdarwin_Darwin','/Mac OS X'#010+
'p*2Tembedded_Embedded'#010+
'p*2Tlinux_Linux'#010+
'R*2Tlinux_Linux'#010+
- 'R','*2Tembedded_Embedded'#010+
+ 'R*2Tembedded_Embedded'#010+
'r*2Tlinux_Linux'#010+
'r*2Tembedded_Embedded'#010+
'S*2Tlinux_Linux'#010+
@@ -1851,161 +1854,166 @@ const msgtxt : array[0..000362,1..240] of char=(
's*2Tlinux_Linux'#010+
'V*2Tembedded_Embedded'#010+
'x*2Tembedded_Embedded'#010+
- 'x*2Tfreertos_FreeRTOS'#010+
+ 'x*2Tfreertos_FreeRTO','S'#010+
'x*2Tlinux_Linux'#010+
'Z*2Tembedded_Embedded'#010+
- 'Z*2Tzxspectrum_ZX Spectru','m'#010+
+ 'Z*2Tzxspectrum_ZX Spectrum'#010+
'Z*2Tmsxdos_MSX-DOS'#010+
'**1u<x>_Undefines the symbol <x>'#010+
'**1U_Unit options:'#010+
'**2Un_Do not check where the unit name matches the file name'#010+
- '**2Ur_Generate release unit files (never automatically recompiled)'#010+
+ '**2Ur_Generate release unit files (never ','automatically recompiled)'#010+
'**2Us_Compile a system unit'#010+
- '**1v<x>_Be ','verbose. <x> is a combination of the following letters:'#010+
+ '**1v<x>_Be verbose. <x> is a combination of the following letters:'#010+
'**2*_e : Show errors (default) 0 : Show nothing (except errors)'#010+
- '**2*_w : Show warnings u : Show unit info'#010+
- '**2*_n : Show notes t : Show tried/used f','iles'#010+
+ '**2*_w : Show warnings u : Show uni','t info'#010+
+ '**2*_n : Show notes t : Show tried/used files'#010+
'**2*_h : Show hints c : Show conditionals'#010+
'**2*_i : Show general info d : Show debug info'#010+
- '**2*_l : Show linenumbers r : Rhide/GCC compatibility mode'#010+
- '**2*_s : Show time stamps q : Show mes','sage numbers'#010+
+ '**2*_l : Show linenumbers r : Rhide/GCC com','patibility mod'+
+ 'e'#010+
+ '**2*_s : Show time stamps q : Show message numbers'#010+
'**2*_a : Show everything x : Show info about invoked tools'+
#010+
'**2*_b : Write file names messages p : Write tree.log with parse tre'+
'e'#010+
- '**2*_ with full path v : Write fpcdebug.txt with'#010+
- '**2*_z : Write outp','ut to stderr lots of debugging info'#010+
+ '**2*_ with full ','path v : Write fpcdebug.txt with'#010+
+ '**2*_z : Write output to stderr lots of debugging info'#010+
'**2*_m<x>,<y> : Do not show messages numbered <x> and <y>'#010+
'F*1V<x>_Append '#039'-<x>'#039' to the used compiler binary name (e.g. f'+
- 'or version)'#010+
+ 'or version',')'#010+
'**1W<x>_Target-specific options (targets)'#010+
- '3*2WA_Specify native ','type application (Windows)'#010+
+ '3*2WA_Specify native type application (Windows)'#010+
'4*2WA_Specify native type application (Windows)'#010+
'A*2WA_Specify native type application (Windows)'#010+
- '3*2Wb_Create a bundle instead of a library (Darwin)'#010+
+ '3*2Wb_Create a bundle instead of a library (Darwin)'#010,
'P*2Wb_Create a bundle instead of a library (Darwin)'#010+
- 'p*2Wb_Create ','a bundle instead of a library (Darwin)'#010+
+ 'p*2Wb_Create a bundle instead of a library (Darwin)'#010+
'a*2Wb_Create a bundle instead of a library (Darwin)'#010+
'A*2Wb_Create a bundle instead of a library (Darwin)'#010+
- '4*2Wb_Create a bundle instead of a library (Darwin)'#010+
- '3*2WB_Create a relocatable image (Windows, Sy','mbian)'#010+
+ '4*2Wb_Create a bundle instead of',' a library (Darwin)'#010+
+ '3*2WB_Create a relocatable image (Windows, Symbian)'#010+
'3*2WB<x>_Set image base to <x> (Windows, Symbian)'#010+
'4*2WB_Create a relocatable image (Windows)'#010+
'4*2WB<x>_Set image base to <x> (Windows)'#010+
- 'A*2WB_Create a relocatable image (Windows, Symbian)'#010+
- 'A*2WB<x>_Set image base to <x> (Windows, Symbia','n)'#010+
+ 'A*2WB_Create a relocatable image (','Windows, Symbian)'#010+
+ 'A*2WB<x>_Set image base to <x> (Windows, Symbian)'#010+
'Z*2WB<x>_Set image base to <x> (ZX Spectrum)'#010+
'3*2WC_Specify console type application (EMX, OS/2, Windows)'#010+
'4*2WC_Specify console type application (Windows)'#010+
- 'A*2WC_Specify console type application (Windows)'#010+
- 'P*2WC_Specify console type applica','tion (Classic Mac OS)'#010+
+ 'A*2WC_Specify cons','ole type application (Windows)'#010+
+ 'P*2WC_Specify console type application (Classic Mac OS)'#010+
'3*2WD_Use DEFFILE to export functions of DLL or EXE (Windows)'#010+
'4*2WD_Use DEFFILE to export functions of DLL or EXE (Windows)'#010+
- 'A*2WD_Use DEFFILE to export functions of DLL or EXE (Windows)'#010+
- '3*2We_Use external resources (Da','rwin)'#010+
+ 'A*2WD_Use DEFFILE to export f','unctions of DLL or EXE (Windows)'#010+
+ '3*2We_Use external resources (Darwin)'#010+
'4*2We_Use external resources (Darwin)'#010+
'a*2We_Use external resources (Darwin)'#010+
'A*2We_Use external resources (Darwin)'#010+
'P*2We_Use external resources (Darwin)'#010+
- 'p*2We_Use external resources (Darwin)'#010+
- '3*2WF_Specify full-screen type application (','EMX, OS/2)'#010+
+ 'p*2We_Use externa','l resources (Darwin)'#010+
+ '3*2WF_Specify full-screen type application (EMX, OS/2)'#010+
'3*2WG_Specify graphic type application (EMX, OS/2, Windows)'#010+
'4*2WG_Specify graphic type application (Windows)'#010+
'A*2WG_Specify graphic type application (Windows)'#010+
- 'P*2WG_Specify graphic type application (Classic Mac OS)'#010+
- '3*2Wi_Use inter','nal resources (Darwin)'#010+
+ 'P*2WG_','Specify graphic type application (Classic Mac OS)'#010+
+ '3*2Wi_Use internal resources (Darwin)'#010+
'4*2Wi_Use internal resources (Darwin)'#010+
'a*2Wi_Use internal resources (Darwin)'#010+
'A*2Wi_Use internal resources (Darwin)'#010+
- 'P*2Wi_Use internal resources (Darwin)'#010+
+ 'P*2Wi_Use internal resources (Darwin)'#010,
'p*2Wi_Use internal resources (Darwin)'#010+
- '3*2WI_Turn on/off the usage',' of import sections (Windows)'#010+
+ '3*2WI_Turn on/off the usage of import sections (Windows)'#010+
'4*2WI_Turn on/off the usage of import sections (Windows)'#010+
'A*2WI_Turn on/off the usage of import sections (Windows)'#010+
- '8*2Wh_Use huge code for units (ignored for models with CODE in a uniqu'+
- 'e segment)'#010+
- '8*2Wm<x>_Set me','mory model'#010+
+ '8*2Wh_Use huge code for units (','ignored for models with CODE in a uni'+
+ 'que segment)'#010+
+ '8*2Wm<x>_Set memory model'#010+
'8*3WmTiny_Tiny memory model'#010+
'8*3WmSmall_Small memory model (default)'#010+
'8*3WmMedium_Medium memory model'#010+
'8*3WmCompact_Compact memory model'#010+
- '8*3WmLarge_Large memory model'#010+
+ '8*3WmLarge_Large memory model'#010,
'8*3WmHuge_Huge memory model'#010+
- '3*2WM<x>_Minimum Mac OS X deployment ','version: 10.4, 10.5.1, ... (Dar'+
- 'win)'#010+
- '4*2WM<x>_Minimum Mac OS X deployment version: 10.4, 10.5.1, ... (Darwi'+
+ '3*2WM<x>_Minimum Mac OS X deployment version: 10.4, 10.5.1, ... (Darwi'+
'n)'#010+
- 'p*2WM<x>_Minimum Mac OS X deployment version: 10.4, 10.5.1, ... (Darwi'+
+ '4*2WM<x>_Minimum Mac OS X deployment version: 10.4, 10.5.1, ... (Darwi'+
'n)'#010+
- 'P*2WM<x>_Minimum Mac OS X deployment version: 10.4, 10.5.1',', ... (Dar'+
+ 'p*2WM<x>_Minimum Mac OS X deployment version: 10.4, 10.5.1, ... (D','ar'+
'win)'#010+
+ 'P*2WM<x>_Minimum Mac OS X deployment version: 10.4, 10.5.1, ... (Darwi'+
+ 'n)'#010+
'3*2WN_Do not generate relocation code, needed for debugging (Windows)'#010+
'4*2WN_Do not generate relocation code, needed for debugging (Windows)'#010+
- 'A*2WN_Do not generate relocation code, needed for debugging (Windows)'#010+
- 'A*2Wp<x>_Specif','y the controller type; see fpc -i or fpc -iu for poss'+
- 'ible values'#010+
- 'm*2Wp<x>_Specify the controller type; see fpc -i or fpc -iu for possib'+
+ 'A*2WN_Do not generat','e relocation code, needed for debugging (Windows'+
+ ')'#010+
+ 'A*2Wp<x>_Specify the controller type; see fpc -i or fpc -iu for possib'+
'le values'#010+
- 'R*2Wp<x>_Specify the controller type; see fpc -i or fpc -iu for possib'+
+ 'm*2Wp<x>_Specify the controller type; see fpc -i or fpc -iu for possib'+
'le values'#010+
- 'V*2Wp<x>_Specif','y the controller type; see fpc -i or fpc -iu for poss'+
+ 'R*2Wp<x>_Specify the controlle','r type; see fpc -i or fpc -iu for poss'+
'ible values'#010+
+ 'V*2Wp<x>_Specify the controller type; see fpc -i or fpc -iu for possib'+
+ 'le values'#010+
'x*2Wp<x>_Specify the controller type; see fpc -i or fpc -iu for possib'+
'le values'#010+
- '3*2WP<x>_Minimum iOS deployment version: 3.0, 5.0.1, ... (iphonesim)'#010+
- '4*2WP<x>_Minimum iOS deplo','yment version: 8.0, 8.0.2, ... (iphonesim)'+
+ '3*2WP<x>_Minimum iOS deploymen','t version: 3.0, 5.0.1, ... (iphonesim)'+
#010+
+ '4*2WP<x>_Minimum iOS deployment version: 8.0, 8.0.2, ... (iphonesim)'#010+
'a*2WP<x>_Minimum iOS deployment version: 7.0, 7.1.2, ... (Darwin)'#010+
- 'A*2WP<x>_Minimum iOS deployment version: 3.0, 5.0.1, ... (Darwin)'#010+
+ 'A*2WP<x>_Minimum iOS deployment version: 3.0, 5.0.1, ... (Darwin)'#010,
'3*2WR_Generate relocation code (Windows)'#010+
- '4*2WR_Generate relocatio','n code (Windows)'#010+
+ '4*2WR_Generate relocation code (Windows)'#010+
'A*2WR_Generate relocation code (Windows)'#010+
'8*2Wt<x>_Set the target executable format'#010+
'8*3Wtexe_Create a DOS .EXE file (default)'#010+
- '8*3Wtcom_Create a DOS .COM file (requires tiny memory model)'#010+
- 'P*2WT_Specify MPW tool type applicati','on (Classic Mac OS)'#010+
+ '8*3Wtcom_Create a DOS .COM file (','requires tiny memory model)'#010+
+ 'P*2WT_Specify MPW tool type application (Classic Mac OS)'#010+
'6*2WQ<x>_Set executable metadata format (Sinclair QL)'#010+
'6*3WQqhdr_Set metadata to QDOS File Header style (default)'#010+
'6*3WQxtcc_Set metadata to XTcc style'#010+
- '**2WX_Enable executable stack (Linux)'#010+
+ '**2WX','_Enable executable stack (Linux)'#010+
'**1X_Executable options:'#010+
- '**2X9_G','enerate linkerscript for GNU Binutils ld older than version 2'+
- '.19.1 (Linux)'#010+
+ '**2X9_Generate linkerscript for GNU Binutils ld older than version 2.1'+
+ '9.1 (Linux)'#010+
'**2Xa_Generate code which allows to use more than 2 GB static data on '+
'64 Bit targets (Linux)'#010+
- '**2Xc_Pass --shared/-dynamic to the linker (BeOS, Darwin, FreeBSD, Lin'+
- 'ux',')'#010+
+ '**2Xc_P','ass --shared/-dynamic to the linker (BeOS, Darwin, FreeBSD, L'+
+ 'inux)'#010+
'**2Xd_Do not search default library path (sometimes required for cross'+
'-compiling when not using -XR)'#010+
'**2Xe_Use external linker'#010+
- '**2Xf_Substitute pthread library name for linking (BSD)'#010+
- '**2Xg_Create debuginfo in a separate file and add a deb','uglink sectio'+
- 'n to executable'#010+
+ '**2Xf_Substitute pthread library name for link','ing (BSD)'#010+
+ '**2Xg_Create debuginfo in a separate file and add a debuglink section '+
+ 'to executable'#010+
'**2XD_Try to link units dynamically (defines FPC_LINK_DYNAMIC)'#010+
'**2Xi_Use internal linker'#010+
- 'L*2XlS<x>_LLVM utilties suffix (e.g. -7 in case clang is called clang-'+
- '7)'#010+
- '**2XLA_Define library substitutions for link','ing'#010+
+ 'L*2XlS<x>_LLVM utilties suffix (e.g. -7 in case clan','g is called clan'+
+ 'g-7)'#010+
+ '**2XLA_Define library substitutions for linking'#010+
'**2XLO_Define order of library linking'#010+
'**2XLD_Exclude default order of standard libraries'#010+
'**2Xm_Generate link map'#010+
- '**2XM<x>_Set the name of the '#039'main'#039' program routine (default i'+
- 's '#039'main'#039')'#010+
- '**2Xn_Use target system native linker instead of G','NU ld (Solaris, AI'+
- 'X)'#010+
+ '**2XM<x>_Set the name of the '#039'main'#039' program routine (defa','ult'+
+ ' is '#039'main'#039')'#010+
+ '**2Xn_Use target system native linker instead of GNU ld (Solaris, AIX)'+
+ #010+
'F*2Xp<x>_First search for the compiler binary in the directory <x>'#010+
'**2XP<x>_Prepend the binutils names with the prefix <x>'#010+
- '**2Xr<x>_Set the linker'#039's rlink-path to <x> (needed for cross comp'+
- 'ile, see the ld manual for mor','e information) (BeOS, Linux)'#010+
+ '**2Xr<x>_Set the linker'#039's rlink','-path to <x> (needed for cross co'+
+ 'mpile, see the ld manual for more information) (BeOS, Linux)'#010+
'**2XR<x>_Prepend <x> to all linker search paths (BeOS, Darwin, FreeBSD'+
', Linux, Mac OS, Solaris)'#010+
'**2Xs_Strip all symbols from executable'#010+
- '**2XS_Try to link units statically (default, defines FPC_LINK_STATIC)'#010+
- '**2Xt','_Link with static libraries (-static is passed to linker)'#010+
+ '**2XS_Try ','to link units statically (default, defines FPC_LINK_STATIC'+
+ ')'#010+
+ '**2Xt_Link with static libraries (-static is passed to linker)'#010+
+ '**2Xu_Generate executable in UF2 format (embedded targets only)'#010+
'**2Xv_Generate table for Virtual Entry calls'#010+
- '**2XV_Use VLink as external linker (default on Amiga, MorphOS)'#010+
+ '**2XV_U','se VLink as external linker (default on Amiga, MorphOS)'+
+ #010+
'**2XX_Try to smartlink units (defines FPC_LINK_SMART)'#010+
- '**','1*_'#010+
+ '**1*_'#010+
'**1?_Show this help'#010+
'**1h_Shows this help without waiting'
);
diff --git a/avx512-0037785/compiler/nadd.pas b/avx512-0037785/compiler/nadd.pas
index b7ba6594fc..6c49f126e9 100644
--- a/avx512-0037785/compiler/nadd.pas
+++ b/avx512-0037785/compiler/nadd.pas
@@ -575,7 +575,7 @@ implementation
var
- t,vl,hp,lefttarget,righttarget, hp2: tnode;
+ t,vl,lefttarget,righttarget: tnode;
lt,rt : tnodetype;
hdef,
rd,ld , inttype: tdef;
@@ -3823,7 +3823,6 @@ implementation
function taddnode.first_add64bitint: tnode;
var
procname: string[31];
- temp: tnode;
power: longint;
begin
result := nil;
diff --git a/avx512-0037785/compiler/nbas.pas b/avx512-0037785/compiler/nbas.pas
index d9047f1157..308c643c09 100644
--- a/avx512-0037785/compiler/nbas.pas
+++ b/avx512-0037785/compiler/nbas.pas
@@ -706,8 +706,10 @@ implementation
function tblocknode.simplify(forinline : boolean): tnode;
+{$ifdef break_inlining}
var
a : array[0..3] of tstatementnode;
+{$endif break_inlining}
begin
result := nil;
{ Warning: never replace a blocknode with another node type,
@@ -1023,8 +1025,8 @@ implementation
if segment <> NR_NO then
Result := gas_regname(segment) + ':'
else
- Result := '';
{$endif defined(x86)}
+ Result := '';
if Assigned(symbol) then
begin
diff --git a/avx512-0037785/compiler/ncal.pas b/avx512-0037785/compiler/ncal.pas
index c1efca2a37..4bf6208858 100644
--- a/avx512-0037785/compiler/ncal.pas
+++ b/avx512-0037785/compiler/ncal.pas
@@ -928,7 +928,10 @@ implementation
reused above) }
left:=ctemprefnode.create(paratemp);
end;
+ { add the finish statements to the call cleanup block }
addstatement(finistat,ctempdeletenode.create(paratemp));
+ aktcallnode.add_done_statement(finiblock);
+
firstpass(fparainit);
firstpass(left);
end;
diff --git a/avx512-0037785/compiler/ncginl.pas b/avx512-0037785/compiler/ncginl.pas
index 08f0245681..b91cc6a6ac 100644
--- a/avx512-0037785/compiler/ncginl.pas
+++ b/avx512-0037785/compiler/ncginl.pas
@@ -406,7 +406,6 @@ implementation
hregisterhi,
{$endif not cpu64bitalu and not cpuhighleveltarget}
hregister : tregister;
- hloc: tlocation;
begin
{ set defaults }
addconstant:=true;
diff --git a/avx512-0037785/compiler/ncgvmt.pas b/avx512-0037785/compiler/ncgvmt.pas
index 2353ce7bc9..e887deea75 100644
--- a/avx512-0037785/compiler/ncgvmt.pas
+++ b/avx512-0037785/compiler/ncgvmt.pas
@@ -708,7 +708,7 @@ implementation
while realintfdef.is_unique_objpasdef do
realintfdef:=realintfdef.childof;
- tmpstr:=_class.objname^+'_$_'+realintfdef.objname^+'_$_'+tostr(i)+'_$_'+pd.mangledname;
+ tmpstr:=_class.objname^+'_$_'+make_mangledname('',realintfdef.owner,'')+'_$$_'+realintfdef.objname^+'_$_'+tostr(i)+'_$_'+pd.mangledname;
if length(tmpstr)>100 then
begin
crc:=0;
diff --git a/avx512-0037785/compiler/ncnv.pas b/avx512-0037785/compiler/ncnv.pas
index 20942a4c0c..4a58772252 100644
--- a/avx512-0037785/compiler/ncnv.pas
+++ b/avx512-0037785/compiler/ncnv.pas
@@ -2947,7 +2947,7 @@ implementation
end;
notn:
result:=docheckremoveinttypeconvs(tunarynode(n).left);
- addn,muln,divn,modn,andn:
+ addn,muln,divn,modn,andn,shln:
begin
if n.nodetype in [divn,modn] then
gotdivmod:=true;
@@ -2986,7 +2986,7 @@ implementation
tempnode: ttempcreatenode;
begin
case n.nodetype of
- subn,addn,muln,divn,modn,xorn,andn,orn:
+ subn,addn,muln,divn,modn,xorn,andn,orn,shln:
begin
exclude(n.flags,nf_internal);
if not forceunsigned and
@@ -3341,20 +3341,20 @@ implementation
to 64 bit }
if (resultdef.size <= 4) and
is_64bitint(left.resultdef) and
- (left.nodetype in [subn,addn,muln,divn,modn,xorn,andn,orn,notn,unaryminusn]) and
+ (left.nodetype in [subn,addn,muln,divn,modn,xorn,andn,orn,notn,unaryminusn,shln]) and
checkremovebiginttypeconvs(left,foundsint,[s8bit,u8bit,s16bit,u16bit,s32bit,u32bit],int64(low(longint)),high(cardinal)) then
doremoveinttypeconvs(left,generrordef,not foundsint,s32inttype,u32inttype);
{$if defined(cpu16bitalu)}
if (resultdef.size <= 2) and
(is_32bitint(left.resultdef) or is_64bitint(left.resultdef)) and
- (left.nodetype in [subn,addn,muln,divn,modn,xorn,andn,orn,notn,unaryminusn]) and
+ (left.nodetype in [subn,addn,muln,divn,modn,xorn,andn,orn,notn,unaryminusn,shln]) and
checkremovebiginttypeconvs(left,foundsint,[s8bit,u8bit,s16bit,u16bit],int64(low(smallint)),high(word)) then
doremoveinttypeconvs(left,generrordef,not foundsint,s16inttype,u16inttype);
{$endif defined(cpu16bitalu)}
{$if defined(cpu8bitalu)}
if (resultdef.size<left.resultdef.size) and
is_integer(left.resultdef) and
- (left.nodetype in [subn,addn,muln,divn,modn,xorn,andn,orn,notn,unaryminusn]) and
+ (left.nodetype in [subn,addn,muln,divn,modn,xorn,andn,orn,notn,unaryminusn,shln]) and
checkremovebiginttypeconvs(left,foundsint,[s8bit,u8bit],int64(low(shortint)),high(byte)) then
doremoveinttypeconvs(left,generrordef,not foundsint,s8inttype,u8inttype);
{$endif defined(cpu8bitalu)}
diff --git a/avx512-0037785/compiler/ncon.pas b/avx512-0037785/compiler/ncon.pas
index dabb8fac44..048624d664 100644
--- a/avx512-0037785/compiler/ncon.pas
+++ b/avx512-0037785/compiler/ncon.pas
@@ -655,7 +655,7 @@ implementation
resultdef:=typedef;
{ only do range checking when explicitly asked for it
and if the type can be range checked, see tests/tbs/tb0539.pp }
- if (resultdef.typ in [orddef,enumdef]) then
+ if (resultdef.typ in [orddef,enumdef]) and not(nf_generic_para in flags) then
adaptrange(resultdef,value,nf_internal in flags,not rangecheck,rangecheck)
end;
diff --git a/avx512-0037785/compiler/nflw.pas b/avx512-0037785/compiler/nflw.pas
index 527484385a..5f6ec1b20e 100644
--- a/avx512-0037785/compiler/nflw.pas
+++ b/avx512-0037785/compiler/nflw.pas
@@ -244,8 +244,9 @@ interface
function pass_1 : tnode;override;
function simplify(forinline:boolean): tnode;override;
protected
- function dogetcopy: tnode;override;
procedure adjust_estimated_stack_size; virtual;
+ public
+ function dogetcopy: tnode;override;
end;
ttryfinallynodeclass = class of ttryfinallynode;
@@ -1557,14 +1558,14 @@ implementation
function tifnode.internalsimplify(warn: boolean) : tnode;
+{$if defined(i386) or defined(x86_64) or defined(xtensa)}
var
thenstmnt, elsestmnt: tnode;
in_nr: tinlinenumber;
paratype: tdef;
+{$endif}
begin
result:=nil;
- elsestmnt:=nil;
- in_nr:=Default(tinlinenumber);
{ optimize constant expressions }
if (left.nodetype=ordconstn) then
begin
@@ -1606,6 +1607,8 @@ implementation
into appropriate min/max intrinsics
}
+ elsestmnt:=nil;
+ in_nr:=Default(tinlinenumber);
if (cs_opt_level2 in current_settings.optimizerswitches) and
(left.nodetype in [gtn,gten,ltn,lten]) and IsSingleStatement(right,thenstmnt) and
((t1=nil) or IsSingleStatement(t1,elsestmnt)) and
@@ -2722,6 +2725,13 @@ implementation
result:=right;
right:=nil;
end;
+ { if the finally block contains no code, we can kill
+ it and just return the try part }
+ if has_no_code(right) and not(assigned(third)) and not(implicitframe) then
+ begin
+ result:=left;
+ left:=nil;
+ end;
end;
diff --git a/avx512-0037785/compiler/ngtcon.pas b/avx512-0037785/compiler/ngtcon.pas
index 2158670d82..f08ec07c21 100644
--- a/avx512-0037785/compiler/ngtcon.pas
+++ b/avx512-0037785/compiler/ngtcon.pas
@@ -150,7 +150,7 @@ uses
defutil,defcmp,
{ pass 1 }
htypechk,procinfo,
- nmem,ncnv,ninl,ncon,nld,
+ nmem,ncnv,ninl,ncon,nld,nadd,
{ parser specific stuff }
pbase,pexpr,
{ codegen }
@@ -826,7 +826,7 @@ function get_next_varsym(def: tabstractrecorddef; const SymList:TFPHashObjectLis
{ maybe pchar ? }
else
if is_char(def.pointeddef) and
- (node.nodetype<>addrn) then
+ ((node.nodetype=stringconstn) or is_constcharnode(node)) then
begin
{ create a tcb for the string data (it's placed in a separate
asmlist) }
@@ -875,7 +875,7 @@ function get_next_varsym(def: tabstractrecorddef; const SymList:TFPHashObjectLis
{ maybe pwidechar ? }
else
if is_widechar(def.pointeddef) and
- (node.nodetype<>addrn) then
+ (node.nodetype in [stringconstn,ordconstn]) then
begin
if (node.nodetype in [stringconstn,ordconstn]) then
begin
@@ -912,13 +912,13 @@ function get_next_varsym(def: tabstractrecorddef; const SymList:TFPHashObjectLis
Message(parser_e_illegal_expression);
end
else
- if (node.nodetype=addrn) or
+ if (node.nodetype in [addrn,addn,subn]) or
is_proc2procvar_load(node,pd) then
begin
{ insert typeconv }
inserttypeconv(node,def);
hp:=node;
- while assigned(hp) and (hp.nodetype in [addrn,typeconvn,subscriptn,vecn]) do
+ while assigned(hp) and (hp.nodetype in [addrn,typeconvn,subscriptn,vecn,addn,subn]) do
hp:=tunarynode(hp).left;
if (hp.nodetype=loadn) then
begin
@@ -927,6 +927,28 @@ function get_next_varsym(def: tabstractrecorddef; const SymList:TFPHashObjectLis
while assigned(hp) and (hp.nodetype<>loadn) do
begin
case hp.nodetype of
+ addn :
+ begin
+ if (is_constintnode(taddnode(hp).right) or
+ is_constenumnode(taddnode(hp).right) or
+ is_constcharnode(taddnode(hp).right) or
+ is_constboolnode(taddnode(hp).right)) and
+ is_pointer(taddnode(hp).left.resultdef) then
+ ftcb.queue_addn(tpointerdef(taddnode(hp).left.resultdef).pointeddef,get_ordinal_value(taddnode(hp).right))
+ else
+ Message(parser_e_illegal_expression);
+ end;
+ subn :
+ begin
+ if (is_constintnode(taddnode(hp).right) or
+ is_constenumnode(taddnode(hp).right) or
+ is_constcharnode(taddnode(hp).right) or
+ is_constboolnode(taddnode(hp).right)) and
+ is_pointer(taddnode(hp).left.resultdef) then
+ ftcb.queue_subn(tpointerdef(taddnode(hp).left.resultdef).pointeddef,get_ordinal_value(taddnode(hp).right))
+ else
+ Message(parser_e_illegal_expression);
+ end;
vecn :
begin
if (is_constintnode(tvecnode(hp).right) or
diff --git a/avx512-0037785/compiler/nmem.pas b/avx512-0037785/compiler/nmem.pas
index c5920e5741..604009fbe7 100644
--- a/avx512-0037785/compiler/nmem.pas
+++ b/avx512-0037785/compiler/nmem.pas
@@ -938,6 +938,7 @@ implementation
htype,elementdef,elementptrdef : tdef;
newordtyp: tordtype;
valid : boolean;
+ minvalue, maxvalue: Tconstexprint;
begin
result:=nil;
typecheckpass(left);
@@ -1051,7 +1052,25 @@ implementation
and not is_64bit(right.resultdef)
{$endif not cpu64bitaddr}
then
- newordtyp:=Torddef(right.resultdef).ordtype
+ begin
+ { in case of an integer type, we need a new type which covers declaration range and index range,
+ see tests/webtbs/tw38413.pp
+
+ This matters only if we sign extend, if the type exceeds the sint range, we can fall back only
+ to the index type
+ }
+ if is_integer(right.resultdef) and ((torddef(right.resultdef).low<0) or (TConstExprInt(Tarraydef(left.resultdef).lowrange)<0)) then
+ begin
+ minvalue:=min(TConstExprInt(Tarraydef(left.resultdef).lowrange),torddef(right.resultdef).low);
+ maxvalue:=max(TConstExprInt(Tarraydef(left.resultdef).highrange),torddef(right.resultdef).high);
+ if maxvalue>torddef(sinttype).high then
+ newordtyp:=Torddef(right.resultdef).ordtype
+ else
+ newordtyp:=range_to_basetype(minvalue,maxvalue);
+ end
+ else
+ newordtyp:=Torddef(right.resultdef).ordtype;
+ end
else
newordtyp:=torddef(sizesinttype).ordtype;
inserttypeconv(right,corddef.create(newordtyp,
diff --git a/avx512-0037785/compiler/ogbase.pas b/avx512-0037785/compiler/ogbase.pas
index 5ed0cf9f0a..543577bee5 100644
--- a/avx512-0037785/compiler/ogbase.pas
+++ b/avx512-0037785/compiler/ogbase.pas
@@ -59,6 +59,8 @@ interface
RELOC_RELATIVE_5,
{ PIC }
RELOC_GOTPCREL,
+ RELOC_GOTPCRELX,
+ RELOC_REX_GOTPCRELX,
RELOC_PLT32,
RELOC_TLSGD,
RELOC_TPOFF,
diff --git a/avx512-0037785/compiler/ogomf.pas b/avx512-0037785/compiler/ogomf.pas
index a78ac903b7..4644e77caa 100644
--- a/avx512-0037785/compiler/ogomf.pas
+++ b/avx512-0037785/compiler/ogomf.pas
@@ -338,15 +338,15 @@ interface
property DwarfUnifiedLogicalSegments: TFPHashObjectList read FExeUnifiedLogicalSegments;
property Header: TMZExeHeader read FHeader;
protected
- procedure Load_Symbol(const aname:string);override;
procedure DoRelocationFixup(objsec:TObjSection);override;
procedure Order_ObjSectionList(ObjSectionList : TFPObjectList;const aPattern:string);override;
- procedure MemPos_ExeSection(const aname:string);override;
- procedure MemPos_EndExeSection;override;
function writeData:boolean;override;
public
constructor create;override;
destructor destroy;override;
+ procedure Load_Symbol(const aname:string);override;
+ procedure MemPos_EndExeSection;override;
+ procedure MemPos_ExeSection(const aname:string);override;
property MZFlatContentSection: TMZExeSection read GetMZFlatContentSection;
end;
@@ -1520,7 +1520,6 @@ implementation
RawRecord: TOmfRawRecord;
i,idx: Integer;
objsym: TObjSymbol;
- ExternalNameElem: TOmfExternalNameElement;
ExtDefRec: TOmfRecord_EXTDEF;
begin
ExtNames:=TFPHashObjectList.Create;
@@ -1532,7 +1531,7 @@ implementation
objsym:=TObjSymbol(Data.ObjSymbolList[i]);
if objsym.bind=AB_EXTERNAL then
begin
- ExternalNameElem:=TOmfExternalNameElement.Create(ExtNames,objsym.Name);
+ TOmfExternalNameElement.Create(ExtNames,objsym.Name);
objsym.symidx:=idx;
Inc(idx);
end;
@@ -1567,7 +1566,6 @@ implementation
SegDef: TOmfRecord_SEGDEF;
GrpDef: TOmfRecord_GRPDEF;
nsections,ngroups: Integer;
- objsym: TObjSymbol;
begin
{ calc amount of sections we have and set their index, starting with 1 }
nsections:=1;
@@ -3157,9 +3155,6 @@ implementation
i: Integer;
ExeSec: TMZExeSection;
ObjSec: TOmfObjSection;
- StartDataPos: LongWord;
- buf: array [0..1023] of byte;
- bytesread: LongWord;
begin
Header.LoadableImageSize:=0;
ExeSec:=MZFlatContentSection;
@@ -3271,7 +3266,6 @@ implementation
i: Integer;
ExeSec: TMZExeSection;
ObjSec: TOmfObjSection;
- StartDataPos: LongWord;
buf: array [0..1023] of byte;
bytesread: LongWord;
begin
@@ -4102,9 +4096,8 @@ cleanup:
function TNewExeEntryTable.GetSize: QWord;
var
- CurBundleStart, i: Integer;
+ CurBundleStart: Integer;
CurBundleSize: Byte;
- cp: TNewExeEntryPoint;
begin
Result:=0;
CurBundleStart:=1;
@@ -4417,7 +4410,7 @@ cleanup:
var
s: TSymStr;
Separator: SizeInt;
- SegName, SegClass: string;
+ {SegName,} SegClass: string;
IsStack, IsBss: Boolean;
begin
{ allow mixing initialized and uninitialized data in the same section
@@ -4429,12 +4422,12 @@ cleanup:
Separator:=Pos('||',s);
if Separator>0 then
begin
- SegName:=Copy(s,1,Separator-1);
+ //SegName:=Copy(s,1,Separator-1);
SegClass:=Copy(s,Separator+2,Length(s)-Separator-1);
end
else
begin
- SegName:=s;
+ //SegName:=s;
SegClass:='';
end;
{ wlink recognizes the stack segment by the class name 'STACK' }
diff --git a/avx512-0037785/compiler/options.pas b/avx512-0037785/compiler/options.pas
index 627882ebb0..4bf2bf35f5 100644
--- a/avx512-0037785/compiler/options.pas
+++ b/avx512-0037785/compiler/options.pas
@@ -1830,6 +1830,7 @@ begin
exclude(init_settings.globalswitches,cs_use_heaptrc);
exclude(init_settings.globalswitches,cs_use_lineinfo);
exclude(init_settings.localswitches,cs_checkpointer);
+ paratargetdbg:=dbg_none;
localvartrashing := -1;
end
else
@@ -2787,6 +2788,18 @@ begin
end;
't' :
include(init_settings.globalswitches,cs_link_staticflag);
+ 'u' :
+ begin
+ if target_info.system in systems_support_uf2 then
+ begin
+ if UnsetBool(More, j, opt, false) then
+ exclude(init_settings.globalswitches,cs_generate_uf2)
+ else
+ include(init_settings.globalswitches,cs_generate_uf2);
+ end
+ else
+ IgnoredPara('-Xu');
+ end;
'v' :
begin
If UnsetBool(More, j, opt, false) then
diff --git a/avx512-0037785/compiler/optloop.pas b/avx512-0037785/compiler/optloop.pas
index 1c613453b7..8f25dfc38b 100644
--- a/avx512-0037785/compiler/optloop.pas
+++ b/avx512-0037785/compiler/optloop.pas
@@ -563,8 +563,6 @@ unit optloop;
function OptimizeForLoop_iterforloops(var n: tnode; arg: pointer): foreachnoderesult;
- var
- hp : tnode;
begin
Result:=fen_false;
if (n.nodetype=forn) and
diff --git a/avx512-0037785/compiler/pdecsub.pas b/avx512-0037785/compiler/pdecsub.pas
index f86f43f55d..b7ce1fda75 100644
--- a/avx512-0037785/compiler/pdecsub.pas
+++ b/avx512-0037785/compiler/pdecsub.pas
@@ -1133,61 +1133,70 @@ implementation
if assigned(genericparams) then
begin
- include(pd.defoptions,df_generic);
- { push the parameter symtable so that constraint definitions are added
- there and not in the owner symtable }
- symtablestack.push(pd.parast);
- { register the parameters }
- for i:=0 to genericparams.count-1 do
+ if potype=potype_constructor then
begin
- tsym(genericparams[i]).register_sym;
- if tsym(genericparams[i]).typ=typesym then
- tstoreddef(ttypesym(genericparams[i]).typedef).register_def;
- end;
- insert_generic_parameter_types(pd,nil,genericparams);
- { the list is no longer required }
- genericparams.free;
- genericparams:=nil;
- symtablestack.pop(pd.parast);
- parse_generic:=true;
- { also generate a dummy symbol if none exists already }
- if assigned(astruct) then
- dummysym:=tsym(astruct.symtable.find(spnongen))
+ Message(parser_e_constructurs_cannot_take_type_parameters);
+ genericparams.free;
+ genericparams:=nil;
+ end
else
begin
- dummysym:=tsym(symtablestack.top.find(spnongen));
- if not assigned(dummysym) and
- (symtablestack.top=current_module.localsymtable) and
- assigned(current_module.globalsymtable) then
- dummysym:=tsym(current_module.globalsymtable.find(spnongen));
- end;
- if not assigned(dummysym) then
- begin
- { overloading generic routines with non-generic types is not
- allowed, so we create a procsym as dummy }
- dummysym:=cprocsym.create(orgspnongen);
+ include(pd.defoptions,df_generic);
+ { push the parameter symtable so that constraint definitions are added
+ there and not in the owner symtable }
+ symtablestack.push(pd.parast);
+ { register the parameters }
+ for i:=0 to genericparams.count-1 do
+ begin
+ tsym(genericparams[i]).register_sym;
+ if tsym(genericparams[i]).typ=typesym then
+ tstoreddef(ttypesym(genericparams[i]).typedef).register_def;
+ end;
+ insert_generic_parameter_types(pd,nil,genericparams);
+ { the list is no longer required }
+ genericparams.free;
+ genericparams:=nil;
+ symtablestack.pop(pd.parast);
+ parse_generic:=true;
+ { also generate a dummy symbol if none exists already }
if assigned(astruct) then
- astruct.symtable.insert(dummysym)
+ dummysym:=tsym(astruct.symtable.find(spnongen))
else
- symtablestack.top.insert(dummysym);
- end
- else if (dummysym.typ<>procsym) and
- (
- { show error only for the declaration, not also the implementation }
- not assigned(astruct) or
- (symtablestack.top.symtablelevel<>main_program_level)
- ) then
- Message1(sym_e_duplicate_id,dummysym.realname);
- if not (sp_generic_dummy in dummysym.symoptions) then
- begin
- include(dummysym.symoptions,sp_generic_dummy);
- add_generic_dummysym(dummysym);
+ begin
+ dummysym:=tsym(symtablestack.top.find(spnongen));
+ if not assigned(dummysym) and
+ (symtablestack.top=current_module.localsymtable) and
+ assigned(current_module.globalsymtable) then
+ dummysym:=tsym(current_module.globalsymtable.find(spnongen));
+ end;
+ if not assigned(dummysym) then
+ begin
+ { overloading generic routines with non-generic types is not
+ allowed, so we create a procsym as dummy }
+ dummysym:=cprocsym.create(orgspnongen);
+ if assigned(astruct) then
+ astruct.symtable.insert(dummysym)
+ else
+ symtablestack.top.insert(dummysym);
+ end
+ else if (dummysym.typ<>procsym) and
+ (
+ { show error only for the declaration, not also the implementation }
+ not assigned(astruct) or
+ (symtablestack.top.symtablelevel<>main_program_level)
+ ) then
+ Message1(sym_e_duplicate_id,dummysym.realname);
+ if not (sp_generic_dummy in dummysym.symoptions) then
+ begin
+ include(dummysym.symoptions,sp_generic_dummy);
+ add_generic_dummysym(dummysym);
+ end;
+ if dummysym.typ=procsym then
+ tprocsym(dummysym).add_generic_overload(aprocsym);
+ { start token recorder for the declaration }
+ pd.init_genericdecl;
+ current_scanner.startrecordtokens(pd.genericdecltokenbuf);
end;
- if dummysym.typ=procsym then
- tprocsym(dummysym).add_generic_overload(aprocsym);
- { start token recorder for the declaration }
- pd.init_genericdecl;
- current_scanner.startrecordtokens(pd.genericdecltokenbuf);
end
else if assigned(genericdef) then
insert_generic_parameter_types(pd,tstoreddef(genericdef),generictypelist);
diff --git a/avx512-0037785/compiler/pgenutil.pas b/avx512-0037785/compiler/pgenutil.pas
index a4de4abf13..4804995dbb 100644
--- a/avx512-0037785/compiler/pgenutil.pas
+++ b/avx512-0037785/compiler/pgenutil.pas
@@ -990,7 +990,7 @@ uses
paramdef2:=tconstsym(tstoreddef(def).genericparas[i]).constdef
else
paramdef2:=ttypesym(tstoreddef(def).genericparas[i]).typedef;
- if not equal_defs(paramdef2,paramdef2) then
+ if not equal_defs(paramdef1,paramdef2) then
begin
allequal:=false;
break;
@@ -1379,8 +1379,6 @@ uses
constraintdata : tgenericconstraintdata;
old_block_type : tblock_type;
fileinfo : tfileposinfo;
- last_token : ttoken;
- last_type_pos : tfileposinfo;
begin
result:=tfphashobjectlist.create(false);
firstidx:=0;
@@ -1389,8 +1387,6 @@ uses
block_type:=bt_type;
allowconst:=true;
is_const:=false;
- last_token:=NOTOKEN;
- last_type_pos:=current_filepos;
repeat
if allowconst and try_to_consume(_CONST) then
begin
@@ -1605,8 +1601,6 @@ uses
is_const:=false;
allowconst:=true;
end;
- last_token:=token;
- last_type_pos:=current_filepos;
until not (try_to_consume(_COMMA) or try_to_consume(_SEMICOLON));
{ if the constant parameter is not terminated then the type restriction was
not specified and we need to give an error }
diff --git a/avx512-0037785/compiler/psabiehpi.pas b/avx512-0037785/compiler/psabiehpi.pas
index d38ebf15ba..c53a073314 100644
--- a/avx512-0037785/compiler/psabiehpi.pas
+++ b/avx512-0037785/compiler/psabiehpi.pas
@@ -688,19 +688,24 @@ implementation
begincatchres,
paraloc1: tcgpara;
pd: tprocdef;
- rttisym: TAsmSymbol;
+ {rttisym: TAsmSymbol;
rttidef: tdef;
+ indirect: boolean;
+ otherunit: boolean; }
wrappedexception: tregister;
exceptloc: tlocation;
- indirect: boolean;
- otherunit: boolean;
+{$if defined(i386) or defined(x86_64)}
typeindex : aint;
+{$endif}
begin
paraloc1.init;
+{
rttidef:=nil;
rttisym:=nil;
+}
wrappedexception:=hlcg.getaddressregister(list,voidpointertype);
hlcg.a_load_reg_reg(list,voidpointertype,voidpointertype,NR_FUNCTION_RESULT_REG,wrappedexception);
+(*
if add_catch then
begin
if assigned(excepttype) then
@@ -715,10 +720,13 @@ implementation
rttisym:=current_asmdata.RefAsmSymbol(excepttype.vmt_mangledname, AT_DATA, indirect);
end;
end;
+*)
{ check if the exception is handled by this node }
if assigned(excepttype) then
begin
+{$if defined(i386) or defined(x86_64)}
typeindex:=(current_procinfo as tpsabiehprocinfo).CurrentAction.AddAction(excepttype);
+{$endif}
current_asmdata.getjumplabel(catchstartlab);
{$if defined(i386)}
hlcg.a_cmp_const_reg_label (list,osuinttype,OC_EQ,typeindex+1,NR_FUNCTION_RESULT64_HIGH_REG,catchstartlab);
diff --git a/avx512-0037785/compiler/psub.pas b/avx512-0037785/compiler/psub.pas
index 0d7ccbabe4..5d31dafcf1 100644
--- a/avx512-0037785/compiler/psub.pas
+++ b/avx512-0037785/compiler/psub.pas
@@ -1312,7 +1312,7 @@ implementation
nodeset : THashSet absolute arg;
entry : ptempinfo_flags_entry;
i : longint;
- hashsetitem: PHashSetItem;
+ {hashsetitem: PHashSetItem;}
begin
result:=fen_true;
case n.nodetype of
diff --git a/avx512-0037785/compiler/rgobj.pas b/avx512-0037785/compiler/rgobj.pas
index 7f4f8ed5fb..b4ad622ae1 100644
--- a/avx512-0037785/compiler/rgobj.pas
+++ b/avx512-0037785/compiler/rgobj.pas
@@ -1692,7 +1692,9 @@ unit rgobj;
colourednodes : Tsuperregisterset;
adj_colours:set of 0..255;
found : boolean;
+{$if declared(RS_STACK_POINTER_REG) and (RS_STACK_POINTER_REG<>RS_INVALID)}
tmpr: tregister;
+{$endif}
begin
spillednodes.clear;
{Reset colours}
@@ -1716,15 +1718,13 @@ unit rgobj;
if supregset_in(colourednodes,a) and (reginfo[a].colour<=255) then
include(adj_colours,reginfo[a].colour);
end;
+ { e.g. AVR does not have a stack pointer register }
+{$if declared(RS_STACK_POINTER_REG) and (RS_STACK_POINTER_REG<>RS_INVALID)}
{ FIXME: temp variable r is needed here to avoid Internal error 20060521 }
{ while compiling the compiler. }
tmpr:=NR_STACK_POINTER_REG;
- { e.g. AVR does not have a stack pointer register }
-{$if defined(RS_STACK_POINTER_REG)}
- {$if (RS_STACK_POINTER_REG<>RS_INVALID)}
if (regtype=getregtype(tmpr)) then
include(adj_colours,RS_STACK_POINTER_REG);
- {$ifend}
{$ifend}
{Assume a spill by default...}
found:=false;
@@ -2521,7 +2521,11 @@ unit rgobj;
{Safe: this procedure is only called if there are spilled nodes.}
with spillednodes do
for i:=0 to length-1 do
- tg.ungetiftemp(list,spill_temps^[buf^[i]]);
+ begin
+ j:=buf^[i];
+ if tg.istemp(spill_temps^[j]) then
+ tg.ungettemp(list,spill_temps^[j]);
+ end;
freemem(spill_temps);
end;
diff --git a/avx512-0037785/compiler/scandir.pas b/avx512-0037785/compiler/scandir.pas
index f695e290c8..6df29a64e6 100644
--- a/avx512-0037785/compiler/scandir.pas
+++ b/avx512-0037785/compiler/scandir.pas
@@ -1362,7 +1362,6 @@ unit scandir;
procedure dir_setpeflags;
var
- ident : string;
flags : int64;
begin
if not (target_info.system in (systems_all_windows)) then
@@ -1378,7 +1377,6 @@ unit scandir;
procedure dir_setpeoptflags;
var
- ident : string;
flags : int64;
begin
if not (target_info.system in (systems_all_windows)) then
diff --git a/avx512-0037785/compiler/scanner.pas b/avx512-0037785/compiler/scanner.pas
index 947d4d558a..649d2bc75a 100644
--- a/avx512-0037785/compiler/scanner.pas
+++ b/avx512-0037785/compiler/scanner.pas
@@ -135,6 +135,8 @@ interface
{ if nexttoken<>NOTOKEN, then nexttokenpos holds its filepos }
next_filepos : tfileposinfo;
+ { current macro nesting depth }
+ macro_nesting_depth,
comment_level,
yylexcount : longint;
ignoredirectives : TFPHashList; { ignore directives, used to give warnings only once }
@@ -2922,7 +2924,10 @@ type
if assigned(inputfile.next) then
begin
if inputfile.is_macro then
- to_dispose:=inputfile
+ begin
+ to_dispose:=inputfile;
+ dec(macro_nesting_depth);
+ end
else
begin
to_dispose:=nil;
@@ -3686,6 +3691,7 @@ type
addfile(hp);
with inputfile do
begin
+ inc(macro_nesting_depth);
setmacro(p,len);
{ local buffer }
inputbuffer:=buf;
@@ -4868,7 +4874,7 @@ type
mac:=tmacro(search_macro(pattern));
if assigned(mac) and (not mac.is_compiler_var) and (assigned(mac.buftext)) then
begin
- if yylexcount<max_macro_nesting then
+ if (yylexcount<max_macro_nesting) and (macro_nesting_depth<max_macro_nesting) then
begin
mac.is_used:=true;
inc(yylexcount);
diff --git a/avx512-0037785/compiler/symdef.pas b/avx512-0037785/compiler/symdef.pas
index 04c0bb64b6..da190640ad 100644
--- a/avx512-0037785/compiler/symdef.pas
+++ b/avx512-0037785/compiler/symdef.pas
@@ -2343,8 +2343,10 @@ implementation
function tstoreddef.is_intregable : boolean;
+{$ifndef cpuhighleveltarget}
var
recsize,temp: longint;
+{$endif cpuhighleveltarget}
begin
case typ of
orddef,
diff --git a/avx512-0037785/compiler/systems.pas b/avx512-0037785/compiler/systems.pas
index 1828b1dfde..a93a2f6c64 100644
--- a/avx512-0037785/compiler/systems.pas
+++ b/avx512-0037785/compiler/systems.pas
@@ -451,6 +451,8 @@ interface
+ [system_i386_beos,system_i386_haiku]
+ [system_powerpc_morphos];
+ systems_support_uf2 = [system_arm_embedded,system_avr_embedded,system_mipsel_embedded,system_xtensa_embedded];
+
{ all internal COFF writers }
asms_int_coff = [as_arm_pecoffwince,as_x86_64_pecoff,as_i386_pecoffwince,
as_i386_pecoffwdosx,as_i386_pecoff,as_i386_coff];
diff --git a/avx512-0037785/compiler/systems/t_amiga.pas b/avx512-0037785/compiler/systems/t_amiga.pas
index 8efdd79a57..03a2896952 100644
--- a/avx512-0037785/compiler/systems/t_amiga.pas
+++ b/avx512-0037785/compiler/systems/t_amiga.pas
@@ -262,6 +262,7 @@ begin
Add(' .data : {');
Add(' PROVIDE(_DATA_BASE_ = .);');
Add(' *(.data .data.* .gnu.linkonce.d.*)');
+ Add(' *(fpc.resources)');
Add(' VBCC_CONSTRUCTORS_ELF');
Add(' }');
Add(' .ctors : { *(.ctors .ctors.*) }');
@@ -293,6 +294,7 @@ begin
Add(' .plt : { *(.plt) }');
Add(' .bss : {');
Add(' *(.bss .bss.* .gnu.linkonce.b.*)');
+ Add(' *(fpc.reshandles)');
Add(' *(COMMON)');
Add(' }');
Add(' .bss68k : { *(BSS bss) }');
diff --git a/avx512-0037785/compiler/systems/t_bsd.pas b/avx512-0037785/compiler/systems/t_bsd.pas
index 14ad1b0298..3fafadece6 100644
--- a/avx512-0037785/compiler/systems/t_bsd.pas
+++ b/avx512-0037785/compiler/systems/t_bsd.pas
@@ -231,7 +231,6 @@ end;
Function TLinkerBSD.WriteResponseFile(isdll:boolean) : Boolean;
Var
linkres : TLinkRes;
- FilesList : TLinkRes;
i : longint;
HPath : TCmdStrListItem;
s,s1,s2 : TCmdStr;
@@ -581,7 +580,6 @@ var
targetstr,
emulstr : TCmdStr;
GCSectionsStr : string[63];
- exportedsyms: text;
success : boolean;
begin
MakeSharedLibrary:=false;
diff --git a/avx512-0037785/compiler/systems/t_darwin.pas b/avx512-0037785/compiler/systems/t_darwin.pas
index 3de7f8a752..2663930879 100644
--- a/avx512-0037785/compiler/systems/t_darwin.pas
+++ b/avx512-0037785/compiler/systems/t_darwin.pas
@@ -320,8 +320,7 @@ implementation
FilesList : TLinkRes;
i : longint;
HPath : TCmdStrListItem;
- s,s1,s2 : TCmdStr;
- Fl1,Fl2 : Boolean;
+ s : TCmdStr;
begin
WriteResponseFile:=False;
if ReOrderEntries Then
@@ -482,7 +481,7 @@ implementation
emulstr:='';
ltostr:='';
if (cs_link_map in current_settings.globalswitches) then
- mapstr:='-Map '+maybequoted(ChangeFileExt(current_module.exefilename,'.map'));
+ mapstr:='-map '+maybequoted(ChangeFileExt(current_module.exefilename,'.map'));
if (cs_link_staticflag in current_settings.globalswitches) then
StaticStr:='-static';
diff --git a/avx512-0037785/compiler/systems/t_embed.pas b/avx512-0037785/compiler/systems/t_embed.pas
index a6e4b684f2..dc53666be8 100644
--- a/avx512-0037785/compiler/systems/t_embed.pas
+++ b/avx512-0037785/compiler/systems/t_embed.pas
@@ -39,6 +39,7 @@ implementation
TlinkerEmbedded=class(texternallinker)
private
Function WriteResponseFile: Boolean;
+ Function GenerateUF2(binFile,uf2File : string;baseAddress : longWord):boolean;
public
constructor Create; override;
procedure SetDefaultInfo; override;
@@ -1653,6 +1654,10 @@ begin
success:=DoExec(FindUtil(utilsprefix+'objcopy'),'-O binary '+
FixedExeFileName+' '+
maybequoted(ScriptFixFileName(ChangeFileExt(current_module.exefilename,'.bin'))),true,false);
+ if success and (target_info.system in systems_support_uf2) and (cs_generate_uf2 in current_settings.globalswitches) then
+ success := GenerateUF2(maybequoted(ScriptFixFileName(ChangeFileExt(current_module.exefilename,'.bin'))),
+ maybequoted(ScriptFixFileName(ChangeFileExt(current_module.exefilename,'.uf2'))),
+ embedded_controllers[current_settings.controllertype].flashbase);
{$ifdef ARM}
if success and (current_settings.controllertype = ct_raspi2) then
success:=DoExec(FindUtil(utilsprefix+'objcopy'),'-O binary '+ FixedExeFileName + ' kernel7.img',true,false);
@@ -1669,6 +1674,106 @@ function TLinkerEmbedded.postprocessexecutable(const fn : string;isdll:boolean):
end;
+function TlinkerEmbedded.GenerateUF2(binFile,uf2File : string;baseAddress : longWord):boolean;
+type
+ TFamilies= record
+ k : String;
+ v : longWord;
+ end;
+ tuf2Block = record
+ magicStart0,
+ magicStart1,
+ flags,
+ targetAddr,
+ payloadSize,
+ blockNo,
+ numBlocks,
+ familyid : longWord;
+ data : array[0..255] of byte;
+ padding : array[0..511-256-32-4] of byte;
+ magicEnd : longWord;
+ end;
+
+const
+ Families : array of TFamilies = (
+ (k:'SAMD21'; v:$68ed2b88),
+ (k:'SAML21'; v:$1851780a),
+ (k:'SAMD51'; v:$55114460),
+ (k:'NRF52'; v:$1b57745f),
+ (k:'STM32F0';v:$647824b6),
+ (k:'STM32F1';v:$5ee21072),
+ (k:'STM32F2';v:$5d1a0a2e),
+ (k:'STM32F3';v:$6b846188),
+ (k:'STM32F4';v:$57755a57),
+ (k:'STM32F7';v:$53b80f00),
+ (k:'STM32G0';v:$300f5633),
+ (k:'STM32G4';v:$4c71240a),
+ (k:'STM32H7';v:$6db66082),
+ (k:'STM32L0';v:$202e3a91),
+ (k:'STM32L1';v:$1e1f432d),
+ (k:'STM32L4';v:$00ff6919),
+ (k:'STM32L5';v:$04240bdf),
+ (k:'STM32WB';v:$70d16653),
+ (k:'STM32WL';v:$21460ff0)
+ );
+
+var
+ f,g : file;
+ uf2block : Tuf2Block;
+ totalRead,numRead : longWord;
+ familyId,i : longWord;
+ ExtraOptions : String;
+
+begin
+ if pos('-Ttext=',Info.ExtraOptions) > 0 then
+ begin
+ ExtraOptions := copy(Info.ExtraOptions,pos('-Ttext=',Info.ExtraOptions)+7,length(Info.ExtraOptions));
+ for i := 1 to length(ExtraOptions) do
+ if pos(copy(ExtraOptions,i,1),'0123456789abcdefxABCDEFX') = 0 then
+ ExtraOptions := copy(ExtraOptions,1,i);
+ baseAddress := StrToIntDef(ExtraOptions,0);
+ end;
+
+ familyId := 0;
+ for i := 0 to length(Families)-1 do
+ begin
+ if pos(Families[i].k,embedded_controllers[current_settings.controllertype].controllerunitstr) = 1 then
+ familyId := Families[i].v;
+ end;
+
+ if (baseAddress and $07ffffff) <> 0 then
+ begin
+ totalRead := 0;
+ numRead := 0;
+ assign(f,binfile);
+ reset(f,1);
+ assign(g,uf2file);
+ rewrite(g,1);
+
+ repeat
+ fillchar(uf2block,sizeof(uf2block),0);
+ uf2block.magicStart0 := $0A324655; // "UF2\n"
+ uf2block.magicStart1 := $9E5D5157; // Randomly selected
+ if familyId = 0 then
+ uf2block.flags := 0
+ else
+ uf2block.flags := $2000;
+ uf2block.targetAddr := baseAddress + totalread;
+ uf2block.payloadSize := 256;
+ uf2block.blockNo := (totalRead div sizeOf(uf2block.data));
+ uf2block.numBlocks := (filesize(f) + 255) div 256;
+ uf2block.familyId := familyId;
+ uf2block.magicEnd := $0AB16F30; // Randomly selected
+ blockRead(f,uf2block.data,sizeof(uf2block.data),numRead);
+ blockwrite(g,uf2block,sizeof(uf2block));
+ inc(totalRead,numRead);
+ until (numRead=0) or (NumRead<>sizeOf(uf2block.data));
+ close(f);
+ close(g);
+ end;
+ Result := true;
+end;
+
{*****************************************************************************
TlinkerEmbedded_SdccSdld
*****************************************************************************}
@@ -1676,17 +1781,14 @@ function TLinkerEmbedded.postprocessexecutable(const fn : string;isdll:boolean):
function TlinkerEmbedded_SdccSdld.WriteResponseFile: Boolean;
Var
linkres : TLinkRes;
- i : longint;
- HPath : TCmdStrListItem;
- s,s1,s2 : TCmdStr;
+ //i : longint;
+ //HPath : TCmdStrListItem;
+ s{,s1,s2} : TCmdStr;
prtobj,
cprtobj : string[80];
linklibc : boolean;
- found1,
- found2 : boolean;
- {$if defined(ARM)}
- LinkStr : string;
- {$endif}
+ //found1,
+ //found2 : boolean;
begin
WriteResponseFile:=False;
linklibc:=(SharedLibFiles.Find('c')<>nil);
diff --git a/avx512-0037785/compiler/systems/t_freertos.pas b/avx512-0037785/compiler/systems/t_freertos.pas
index d3e36d923a..027d29f15c 100644
--- a/avx512-0037785/compiler/systems/t_freertos.pas
+++ b/avx512-0037785/compiler/systems/t_freertos.pas
@@ -81,8 +81,7 @@ Var
i : longint;
HPath : TCmdStrListItem;
s,s1,s2 : TCmdStr;
- prtobj,
- cprtobj : string[80];
+ prtobj : string[80];
linklibc : boolean;
found1,
found2 : boolean;
@@ -96,9 +95,8 @@ begin
prtobj:='';
{$else}
prtobj:='prt0';
- cprtobj:='cprt0';
if linklibc then
- prtobj:=cprtobj;
+ prtobj:='cprt0';
{$endif}
{ Open link.res file }
@@ -944,7 +942,6 @@ end;
function TlinkerFreeRTOS.MakeExecutable:boolean;
var
StaticStr,
- S,
binstr,
cmdstr,
mapstr: Ansistring;
@@ -953,9 +950,12 @@ var
DynLinkStr,
StripStr,
FixedExeFileName: string;
+{$ifdef XTENSA}
+ S: Ansistring;
t: Text;
hp: TCmdStrListItem;
filepath: TCmdStr;
+{$endif XTENSA}
begin
{$ifdef XTENSA}
{ idfpath can be set by -Ff, else default to environment value of IDF_PATH }
diff --git a/avx512-0037785/compiler/systems/t_win.pas b/avx512-0037785/compiler/systems/t_win.pas
index 887787f8e9..05e50d1c94 100644
--- a/avx512-0037785/compiler/systems/t_win.pas
+++ b/avx512-0037785/compiler/systems/t_win.pas
@@ -430,7 +430,9 @@ implementation
l1,l2,l3,l4 {$ifdef ARM} ,l5 {$endif ARM} : tasmlabel;
importname : string;
suffix : integer;
+{$ifndef AARCH64}
href : treference;
+{$endif AARCH64}
i,j : longint;
ImportLibrary : TImportLibrary;
ImportSymbol : TImportSymbol;
diff --git a/avx512-0037785/compiler/systems/t_win16.pas b/avx512-0037785/compiler/systems/t_win16.pas
index 8b76d09151..587c121a69 100644
--- a/avx512-0037785/compiler/systems/t_win16.pas
+++ b/avx512-0037785/compiler/systems/t_win16.pas
@@ -104,7 +104,6 @@ var
i,j: Integer;
ImportLibrary: TImportLibrary;
ImportSymbol: TImportSymbol;
- AsmPrefix: String;
procedure AddImport(const dllname,afuncname,mangledname:string;ordnr:longint;isvar:boolean);
begin
@@ -114,7 +113,6 @@ var
end;
begin
- AsmPrefix:='imp'+Lower(current_module.modulename^);
current_module.linkotherstaticlibs.add(current_module.importlibfilename,link_always);
ObjWriter:=TOmfLibObjectWriter.CreateAr(current_module.importlibfilename,32);
ObjOutput:=TOmfObjOutput.Create(ObjWriter);
@@ -238,7 +236,6 @@ function TExternalLinkerWin16WLink.WriteResponseFile(isdll: boolean): Boolean;
Var
linkres : TLinkRes;
s : string;
- i: Integer;
begin
WriteResponseFile:=False;
diff --git a/avx512-0037785/compiler/utils/Makefile b/avx512-0037785/compiler/utils/Makefile
index aa2def26a7..3b69835f57 100644
--- a/avx512-0037785/compiler/utils/Makefile
+++ b/avx512-0037785/compiler/utils/Makefile
@@ -351,316 +351,316 @@ ifdef OPTNEW
override FPCOPT+=$(OPTNEW)
endif
ifeq ($(FULL_TARGET),i386-linux)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),i386-go32v2)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),i386-win32)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),i386-os2)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),i386-freebsd)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),i386-beos)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),i386-haiku)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),i386-netbsd)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),i386-solaris)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),i386-netware)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),i386-openbsd)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),i386-wdosx)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),i386-darwin)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),i386-emx)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),i386-watcom)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),i386-netwlibc)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),i386-wince)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),i386-embedded)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),i386-symbian)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),i386-nativent)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),i386-iphonesim)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),i386-android)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),i386-aros)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),m68k-linux)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),m68k-netbsd)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),m68k-amiga)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),m68k-atari)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),m68k-palmos)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),m68k-macosclassic)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),m68k-embedded)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),m68k-sinclairql)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),powerpc-linux)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),powerpc-netbsd)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),powerpc-amiga)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),powerpc-macosclassic)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),powerpc-darwin)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),powerpc-morphos)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),powerpc-embedded)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),powerpc-wii)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),powerpc-aix)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),sparc-linux)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),sparc-netbsd)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),sparc-solaris)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),sparc-embedded)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),x86_64-linux)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),x86_64-freebsd)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),x86_64-haiku)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),x86_64-netbsd)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),x86_64-solaris)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),x86_64-openbsd)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),x86_64-darwin)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),x86_64-win64)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),x86_64-embedded)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),x86_64-iphonesim)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),x86_64-android)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),x86_64-aros)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),x86_64-dragonfly)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),arm-linux)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),arm-netbsd)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),arm-palmos)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),arm-wince)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),arm-gba)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),arm-nds)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),arm-embedded)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),arm-symbian)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),arm-android)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),arm-aros)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),arm-freertos)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),arm-ios)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),powerpc64-linux)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),powerpc64-darwin)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),powerpc64-embedded)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),powerpc64-aix)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),avr-embedded)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),armeb-linux)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),armeb-embedded)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),mips-linux)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),mipsel-linux)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),mipsel-embedded)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),mipsel-android)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),mips64el-linux)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),jvm-java)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),jvm-android)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),i8086-embedded)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),i8086-msdos)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),i8086-win16)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),aarch64-linux)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),aarch64-darwin)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),aarch64-win64)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),aarch64-android)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),aarch64-ios)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),wasm-wasm)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),sparc64-linux)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),riscv32-linux)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),riscv32-embedded)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),riscv64-linux)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),riscv64-embedded)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),xtensa-linux)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),xtensa-embedded)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),xtensa-freertos)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),z80-embedded)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),z80-zxspectrum)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),z80-msxdos)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),z80-amstradcpc)
-override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
endif
ifeq ($(FULL_TARGET),i386-linux)
override CLEAN_UNITS+=ppu crc
diff --git a/avx512-0037785/compiler/utils/Makefile.fpc b/avx512-0037785/compiler/utils/Makefile.fpc
index be979a987e..1ae4baa30c 100644
--- a/avx512-0037785/compiler/utils/Makefile.fpc
+++ b/avx512-0037785/compiler/utils/Makefile.fpc
@@ -3,7 +3,7 @@
#
[target]
-programs=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
+programs=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins msg2inc mkx86inl mkz80ins
rst=fpcsubst
[clean]
diff --git a/avx512-0037785/compiler/utils/mkx86inl.pp b/avx512-0037785/compiler/utils/mkx86inl.pp
index 92e218306c..fe784a2c7e 100644
--- a/avx512-0037785/compiler/utils/mkx86inl.pp
+++ b/avx512-0037785/compiler/utils/mkx86inl.pp
@@ -4,8 +4,7 @@ program mkx86inl;
{$H+}
uses
- sysutils, classes,
- strutils;
+ sysutils, classes;
type
TOperDirection = (operIn, operVar, operOut);
@@ -19,6 +18,93 @@ type
const
DirLUT: array[TOperDirection] of string = ('','var ','out ');
+{ ***************************************************************************
+ the routines Copy2SymbDel, PosSetEx, PosSet, RemoveTrailingChars, TrimRightSet are copied and reformatted
+ from StrUtils and thus covered by the copyright of strutils (see below) as compiler utilities cannot
+ depend on packages
+
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 1999-2005 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.
+*************************************************************************** }
+
+function Copy2SymbDel(var S: string; Symb: Char): string;
+ var
+ p: SizeInt;
+ begin
+ p:=Pos(Symb,S);
+ if p=0 then
+ begin
+ result:=s;
+ s:='';
+ end
+ else
+ begin
+ Result:=Copy(S,1,p-1);
+ delete(s,1,p);
+ end;
+ end;
+
+
+function PosSetEx(const c: TSysCharSet; const s: ansistring; count: Integer): SizeInt;
+ var
+ i,j:SizeInt;
+ begin
+ if pchar(pointer(s))=nil then
+ j:=0
+ else
+ begin
+ i:=length(s);
+ j:=count;
+ if j>i then
+ begin
+ result:=0;
+ exit;
+ end;
+ while (j<=i) and (not (s[j] in c)) do inc(j);
+ if (j>i) then
+ j:=0; // not found.
+ end;
+ result:=j;
+ end;
+
+function PosSet(const c: TSysCharSet; const s: ansistring): SizeInt;
+ begin
+ result:=possetex(c,s,1);
+ end;
+
+procedure RemoveTrailingChars(VAR S: AnsiString; const CSet: TSysCharset);
+ var
+ I,J: LONGINT;
+
+ Begin
+ I:=Length(S);
+ IF (I>0) Then
+ Begin
+ J:=I;
+ While (j>0) and (S[J] IN CSet) DO DEC(J);
+ IF J<>I Then
+ SetLength(S,J);
+ End;
+ End;
+
+function TrimRightSet(const S: String; const CSet: TSysCharSet): String;
+
+begin
+ result:=s;
+ RemoveTrailingchars(result,cset);
+end;
+
+{ ***************************************************************************
+ end of StrUtils code
+ ***************************************************************************}
+
function GetPascalType(const ATyp: string): string;
begin
case ATyp of
diff --git a/avx512-0037785/compiler/utils/mkz80ins.pp b/avx512-0037785/compiler/utils/mkz80ins.pp
index 3c12563fa1..f94e752731 100644
--- a/avx512-0037785/compiler/utils/mkz80ins.pp
+++ b/avx512-0037785/compiler/utils/mkz80ins.pp
@@ -18,7 +18,7 @@ program mkz80ins;
{$mode objfpc}{$H+}
uses
- SysUtils,StrUtils;
+ SysUtils;
const
Version = '1.0.0';
@@ -84,6 +84,37 @@ type
destructor Destroy;override;
end;
+{ ***************************************************************************
+ the routines LeftStr, AnsiStartsStr are copied and reformatted
+ from StrUtils and thus covered by the copyright of strutils (see below) as compiler utilities cannot
+ depend on packages
+
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 1999-2005 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.
+*************************************************************************** }
+
+function LeftStr(const AText: AnsiString; const ACount: SizeInt): AnsiString;
+ begin
+ Result:=Copy(AText,1,ACount);
+ end;
+
+
+function AnsiStartsStr(const ASubText, AText: string): Boolean;
+ begin
+ Result := (ASubText = '') or (LeftStr(AText, Length(ASubText)) = ASubText);
+ end;
+
+{ ***************************************************************************
+ end of StrUtils code
+***************************************************************************}
+
function PasEncode(const S: string): string;
var
Ch: Char;
diff --git a/avx512-0037785/compiler/utils/msg2inc.pp b/avx512-0037785/compiler/utils/msg2inc.pp
index 9e8e45787f..38a7c7f700 100644
--- a/avx512-0037785/compiler/utils/msg2inc.pp
+++ b/avx512-0037785/compiler/utils/msg2inc.pp
@@ -13,6 +13,7 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
**********************************************************************}
+{$H+}
program msg2inc;
{$ifdef unix}
@@ -622,21 +623,28 @@ Var
hs : string;
begin
hs:='';
- for i:=1 to length(s) do
- case S[i] of
- '$' :
- if (s[i+1] in ['0'..'9']) then
- hs:=hs+'arg'
- else
- hs:=hs+'\$';
- '&','{','}','#','_','%': // Escape these characters
- hs := hs + '\' + S[i];
- '~','^':
- hs := hs + '\'+S[i]+' ';
- '\':
- hs:=hs+'$\backslash$'
- else
- hs := hs + S[i];
+ i:=1;
+ while i<=length(s) do
+ begin
+ case S[i] of
+ '$' :
+ if (s[i+1] in ['0'..'9']) then
+ begin
+ hs:=hs+'\textlangle arg. '+s[i+1]+'\textrangle{}';
+ inc(i);
+ end
+ else
+ hs:=hs+'\$';
+ '&','{','}','#','_','%': // Escape these characters
+ hs := hs + '\' + S[i];
+ '~','^':
+ hs := hs + '\'+S[i]+' ';
+ '\':
+ hs:=hs+'$\backslash$'
+ else
+ hs := hs + S[i];
+ end;
+ inc(i);
end;
EscapeString:=hs;
end;
@@ -646,6 +654,7 @@ var
t,f : text;
line,
i,k : longint;
+ number,
s,s1 : string;
texoutput : boolean;
begin
@@ -695,25 +704,35 @@ begin
if i>0 then
begin
inc(i);
+ number:='';
while s[i] in ['0'..'9'] do
- inc(i);
+ begin
+ number:=number+s[i];
+ inc(i);
+ end;
+ { strip leading zeros }
+ while number[1]='0' do
+ Delete(number,1,1);
inc(i);
s1:='';
k:=0;
while (k<5) and (s[i+k]<>'_') do
begin
case s[i+k] of
- 'W' : s1:='Warning: ';
- 'E' : s1:='Error: ';
- 'F' : s1:='Fatal: ';
- 'N' : s1:='Note: ';
- 'I' : s1:='Info: ';
- 'H' : s1:='Hint: ';
+ 'W' : s1:='Warning '+number+': ';
+ 'E' : s1:='Error '+number+': ';
+ 'F' : s1:='Fatal error '+number+': ';
+ 'N' : s1:='Note '+number+': ';
+ 'I' : s1:='Info '+number+': ';
+ 'H' : s1:='Hint '+number+': ';
end;
inc(k);
end;
if s[i+k]='_' then
inc(i,k+1);
+ if number<>'' then
+ writeln(t,'\index[msgnr]{',number,'}');
+ writeln(t,'\index[msgtxt]{',escapestring(Copy(s,i,255)),'}');
writeln(t,'\item ['+s1+escapestring(Copy(s,i,255))+'] \hfill \\');
end
else
diff --git a/avx512-0037785/compiler/utils/ppuutils/ppudump.pp b/avx512-0037785/compiler/utils/ppuutils/ppudump.pp
index bc06c393d5..50f708105c 100644
--- a/avx512-0037785/compiler/utils/ppuutils/ppudump.pp
+++ b/avx512-0037785/compiler/utils/ppuutils/ppudump.pp
@@ -2305,7 +2305,8 @@ const
'Link using vlink', {cs_link_vlink}
'Link-Time Optimization disabled for system unit', {cs_lto_nosystem}
'Assemble on target OS', {cs_asemble_on_target}
- 'Use a memory model to support >2GB static data on 64 Bit target' {cs_large}
+ 'Use a memory model to support >2GB static data on 64 Bit target', {cs_large}
+ 'Generate UF2 binary' {cs_generate_uf2}
);
localswitchname : array[tlocalswitch] of string[50] =
{ Switches which can be changed locally }
diff --git a/avx512-0037785/compiler/verbose.pas b/avx512-0037785/compiler/verbose.pas
index a6003eeaf2..bc48697a02 100644
--- a/avx512-0037785/compiler/verbose.pas
+++ b/avx512-0037785/compiler/verbose.pas
@@ -753,7 +753,7 @@ implementation
UpdateStatus;
{ Fix replacements }
DefaultReplacements(s);
- if status.showmsgnrs then
+ if status.showmsgnrs and ((v and V_Normal)=0) then
s:='('+tostr(w)+') '+s;
if doqueue then
begin
diff --git a/avx512-0037785/compiler/x86/aasmcpu.pas b/avx512-0037785/compiler/x86/aasmcpu.pas
index 699e009466..eeb6044d77 100644
--- a/avx512-0037785/compiler/x86/aasmcpu.pas
+++ b/avx512-0037785/compiler/x86/aasmcpu.pas
@@ -924,6 +924,7 @@ implementation
Intel 64 and IA-32 Architectures Software Developer’s Manual
Volume 2B: Instruction Set Reference, N-Z, January 2015
}
+{$ifndef i8086}
alignarray_cmovcpus:array[0..10] of string[11]=(
#$66#$66#$66#$0F#$1F#$84#$00#$00#$00#$00#$00,
#$66#$66#$0F#$1F#$84#$00#$00#$00#$00#$00,
@@ -936,6 +937,7 @@ implementation
#$0F#$1F#$00,
#$66#$90,
#$90);
+{$endif i8086}
{$ifdef i8086}
alignarray:array[0..5] of string[8]=(
#$90#$90#$90#$90#$90#$90#$90,
@@ -3690,13 +3692,17 @@ implementation
needed_VEX_Extension: boolean;
needed_VEX: boolean;
needed_EVEX: boolean;
+{$ifdef x86_64}
needed_VSIB: boolean;
+{$endif x86_64}
opmode: integer;
VEXvvvv: byte;
VEXmmmmm: byte;
+{
VEXw : byte;
VEXpp : byte;
VEXll : byte;
+}
EVEXvvvv: byte;
EVEXpp: byte;
EVEXr: byte;
@@ -3795,14 +3801,17 @@ implementation
needed_VEX := false;
needed_EVEX := false;
needed_VEX_Extension := false;
+{$ifdef x86_64}
needed_VSIB := false;
+{$endif x86_64}
opmode := -1;
VEXvvvv := 0;
VEXmmmmm := 0;
-
+{
VEXll := 0;
VEXw := 0;
VEXpp := 0;
+}
EVEXpp := 0;
EVEXvvvv := 0;
EVEXr := 0;
@@ -3855,7 +3864,9 @@ implementation
begin
// VSIB memory addresing
if getsupreg(oper[opidx]^.ref^.index) and $10 = $0 then EVEXv := 1; // VECTOR-Index
+ {$ifdef x86_64}
needed_VSIB := true;
+ {$endif x86_64}
end;
end;
else
@@ -3866,12 +3877,12 @@ implementation
end;
&333: begin
VEXvvvv := VEXvvvv OR $02; // set SIMD-prefix $F3
- VEXpp := $02; // set SIMD-prefix $F3
+ //VEXpp := $02; // set SIMD-prefix $F3
EVEXpp := $02; // set SIMD-prefix $F3
end;
&334: begin
VEXvvvv := VEXvvvv OR $03; // set SIMD-prefix $F2
- VEXpp := $03; // set SIMD-prefix $F2
+ //VEXpp := $03; // set SIMD-prefix $F2
EVEXpp := $03; // set SIMD-prefix $F2
end;
&350: needed_EVEX := true; // AVX512 instruction or AVX128/256/512-instruction (depended on operands [x,y,z]mm16..)
@@ -3879,18 +3890,18 @@ implementation
&352: EVEXw1 := $01;
&361: begin
VEXvvvv := VEXvvvv OR $01; // set SIMD-prefix $66
- VEXpp := $01; // set SIMD-prefix $66
+ //VEXpp := $01; // set SIMD-prefix $66
EVEXpp := $01; // set SIMD-prefix $66
end;
&362: needed_VEX := true;
&363: begin
needed_VEX_Extension := true;
VEXvvvv := VEXvvvv OR (1 shl 7); // set REX.W
- VEXw := 1;
+ //VEXw := 1;
end;
&364: begin
VEXvvvv := VEXvvvv OR $04; // vectorlength = 256 bits AND no scalar
- VEXll := $01;
+ //VEXll := $01;
EVEXll := $01;
end;
&366,
diff --git a/avx512-0037785/compiler/x86/agx86nsm.pas b/avx512-0037785/compiler/x86/agx86nsm.pas
index cbff191756..a4f28adafe 100644
--- a/avx512-0037785/compiler/x86/agx86nsm.pas
+++ b/avx512-0037785/compiler/x86/agx86nsm.pas
@@ -53,7 +53,9 @@ interface
private
FSections: TFPHashObjectList;
FGroups: TFPHashObjectList;
+{$ifndef i8086}
using_relative : boolean;
+{$endif i8086}
function CodeSectionName(const aname:string): string;
procedure WriteReference(var ref : treference);
procedure WriteOper(const o:toper;s : topsize; opcode: tasmop;ops:longint;dest : boolean);
@@ -681,10 +683,6 @@ interface
end;
procedure TX86NasmAssembler.WriteGroups;
- {$ifdef i8086}
- var
- i: Integer;
- {$endif i8086}
begin
{$ifdef i8086}
if target_info.system in [system_i8086_msdos,system_i8086_win16,system_i8086_embedded] then
diff --git a/avx512-0037785/compiler/x86/aoptx86.pas b/avx512-0037785/compiler/x86/aoptx86.pas
index 4b38629c44..83fc2deb84 100644
--- a/avx512-0037785/compiler/x86/aoptx86.pas
+++ b/avx512-0037785/compiler/x86/aoptx86.pas
@@ -122,6 +122,7 @@ unit aoptx86;
function PrePeepholeOptSxx(var p : tai) : boolean;
function PrePeepholeOptIMUL(var p : tai) : boolean;
+ function OptPass1Add(var p: tai): boolean;
function OptPass1AND(var p : tai) : boolean;
function OptPass1_V_MOVAP(var p : tai) : boolean;
function OptPass1VOP(var p : tai) : boolean;
@@ -1653,9 +1654,6 @@ unit aoptx86;
{ Replaces all references to AOldReg in a memory reference to ANewReg }
class function TX86AsmOptimizer.ReplaceRegisterInRef(var ref: TReference; const AOldReg, ANewReg: TRegister): Boolean;
- var
- OldSupReg: TSuperRegister;
- OldSubReg, MemSubReg: TSubRegister;
begin
Result := False;
{ For safety reasons, only check for exact register matches }
@@ -1680,7 +1678,7 @@ unit aoptx86;
class function TX86AsmOptimizer.ReplaceRegisterInOper(const p: taicpu; const OperIdx: Integer; const AOldReg, ANewReg: TRegister): Boolean;
var
OldSupReg, NewSupReg: TSuperRegister;
- OldSubReg, NewSubReg, MemSubReg: TSubRegister;
+ OldSubReg, NewSubReg: TSubRegister;
OldRegType: TRegisterType;
ThisOper: POper;
begin
@@ -1838,7 +1836,6 @@ unit aoptx86;
function TX86AsmOptimizer.DeepMOVOpt(const p_mov: taicpu; const hp: taicpu): Boolean;
var
CurrentReg, ReplaceReg: TRegister;
- SubReg: TSubRegister;
begin
Result := False;
@@ -3171,10 +3168,45 @@ unit aoptx86;
end;
+ function TX86AsmOptimizer.OptPass1Add(var p : tai) : boolean;
+ var
+ hp1 : tai;
+ begin
+ result:=false;
+ { replace
+ addX const,%reg1
+ leaX (%reg1,%reg1,Y),%reg2 // Base or index might not be equal to reg1
+ dealloc %reg1
+
+ by
+
+ leaX const+const*Y(%reg1,%reg1,Y),%reg2
+ }
+ if MatchOpType(taicpu(p),top_const,top_reg) and
+ GetNextInstruction(p,hp1) and
+ MatchInstruction(hp1,A_LEA,[taicpu(p).opsize]) and
+ ((taicpu(p).oper[1]^.reg=taicpu(hp1).oper[0]^.ref^.base) or
+ (taicpu(p).oper[1]^.reg=taicpu(hp1).oper[0]^.ref^.index)) then
+ begin
+ TransferUsedRegs(TmpUsedRegs);
+ UpdateUsedRegs(TmpUsedRegs, tai(p.next));
+ if not(RegUsedAfterInstruction(taicpu(p).oper[1]^.reg,hp1,TmpUsedRegs)) then
+ begin
+ DebugMsg(SPeepholeOptimization + 'AddLea2Lea done',p);
+ if taicpu(p).oper[1]^.reg=taicpu(hp1).oper[0]^.ref^.base then
+ inc(taicpu(hp1).oper[0]^.ref^.offset,taicpu(p).oper[0]^.val);
+ if taicpu(p).oper[1]^.reg=taicpu(hp1).oper[0]^.ref^.index then
+ inc(taicpu(hp1).oper[0]^.ref^.offset,taicpu(p).oper[0]^.val*max(taicpu(hp1).oper[0]^.ref^.scalefactor,1));
+ RemoveCurrentP(p);
+ result:=true;
+ end;
+ end;
+ end;
+
+
function TX86AsmOptimizer.OptPass1LEA(var p : tai) : boolean;
var
- hp1, hp2, hp3: tai;
- l : ASizeInt;
+ hp1: tai;
ref: Integer;
saveref: treference;
TempReg: TRegister;
@@ -3350,7 +3382,11 @@ unit aoptx86;
) or
((taicpu(hp1).oper[0]^.ref^.base=taicpu(p).oper[1]^.reg) and
(taicpu(hp1).oper[0]^.ref^.scalefactor <= 1) and
- (taicpu(p).oper[0]^.ref^.base=NR_NO) and
+ ((taicpu(p).oper[0]^.ref^.base=NR_NO) or
+ ((taicpu(p).oper[0]^.ref^.base=taicpu(p).oper[0]^.ref^.base) and
+ (taicpu(p).oper[0]^.ref^.index=NR_NO)
+ )
+ ) and
not(RegUsedBetween(taicpu(p).oper[0]^.ref^.index,p,hp1)))
) and
not(RegUsedBetween(taicpu(p).oper[0]^.ref^.base,p,hp1)) and
@@ -4945,7 +4981,7 @@ unit aoptx86;
MinSize, MaxSize, TrySmaller, TargetSize: TOpSize;
TargetSubReg: TSubRegister;
hp1, hp2: tai;
- RegInUse, p_removed: Boolean;
+ RegInUse, RegChanged, p_removed: Boolean;
{ Store list of found instructions so we don't have to call
GetNextInstructionUsingReg multiple times }
@@ -4995,6 +5031,7 @@ unit aoptx86;
TrySmallerLimit := UpperLimit;
TrySmaller := S_NO;
SmallerOverflow := False;
+ RegChanged := False;
while GetNextInstructionUsingReg(hp1, hp1, ThisReg) and
(hp1.typ = ait_instruction) and
@@ -5377,6 +5414,7 @@ unit aoptx86;
begin
DebugMsg(SPeepholeOptimization + 'Simplified register usage so ' + debug_regname(taicpu(hp1).oper[1]^.reg) + ' = ' + debug_regname(taicpu(p).oper[1]^.reg), p);
ThisReg := taicpu(hp1).oper[1]^.reg;
+ RegChanged := True;
TransferUsedRegs(TmpUsedRegs);
AllocRegBetween(ThisReg, p, hp1, TmpUsedRegs);
@@ -5411,9 +5449,12 @@ unit aoptx86;
{ Now go through every instruction we found and change the
size. If TargetSize = MaxSize, then almost no changes are
needed and Result can remain False if it hasn't been set
- yet. }
+ yet.
+
+ If RegChanged is True, then the register requires changing
+ and so the point about TargetSize = MaxSize doesn't apply. }
- if (TargetSize <> MaxSize) and (InstrMax >= 0) then
+ if ((TargetSize <> MaxSize) or RegChanged) and (InstrMax >= 0) then
begin
for Index := 0 to InstrMax do
begin
@@ -5640,99 +5681,100 @@ unit aoptx86;
function TX86AsmOptimizer.OptPass2Jcc(var p : tai) : boolean;
var
- hp1,hp2,hp3,hp4,hpmov2: tai;
- carryadd_opcode : TAsmOp;
+ hp1,hp2: tai;
+{$ifndef i8086}
+ hp3,hp4,hpmov2: tai;
l : Longint;
condition : TAsmCond;
+{$endif i8086}
+ carryadd_opcode : TAsmOp;
symbol: TAsmSymbol;
reg: tsuperregister;
- regavailable: Boolean;
+ increg, tmpreg: TRegister;
begin
result:=false;
- symbol:=nil;
- if GetNextInstruction(p,hp1) then
+ if GetNextInstruction(p,hp1) and (hp1.typ=ait_instruction) then
begin
symbol := TAsmLabel(taicpu(p).oper[0]^.ref^.symbol);
- if (hp1.typ=ait_instruction) and
- GetNextInstruction(hp1,hp2) and
- ((hp2.typ=ait_label) or
- { trick to skip align }
+ if GetNextInstruction(hp1,hp2) and
+ (
+ (hp2.typ=ait_label) or
+ { trick to skip align }
((hp2.typ=ait_align) and GetNextInstruction(hp2,hp2) and (hp2.typ=ait_label))
- ) and
- (Tasmlabel(symbol) = Tai_label(hp2).labsym) then
- { jb @@1 cmc
- inc/dec operand --> adc/sbb operand,0
- @@1:
+ ) and
+ (Tasmlabel(symbol) = Tai_label(hp2).labsym) and
+ (
+ (
+ ((Taicpu(hp1).opcode=A_ADD) or (Taicpu(hp1).opcode=A_SUB)) and
+ MatchOptype(Taicpu(hp1),top_const,top_reg) and
+ (Taicpu(hp1).oper[0]^.val=1)
+ ) or
+ ((Taicpu(hp1).opcode=A_INC) or (Taicpu(hp1).opcode=A_DEC))
+ ) then
+ { jb @@1 cmc
+ inc/dec operand --> adc/sbb operand,0
+ @@1:
- ... and ...
+ ... and ...
- jnb @@1
- inc/dec operand --> adc/sbb operand,0
- @@1: }
+ jnb @@1
+ inc/dec operand --> adc/sbb operand,0
+ @@1: }
begin
- carryadd_opcode:=A_NONE;
if Taicpu(p).condition in [C_NAE,C_B,C_C] then
begin
- if (Taicpu(hp1).opcode=A_INC) or
- ((Taicpu(hp1).opcode=A_ADD) and
- MatchOptype(Taicpu(hp1),top_const,top_reg) and
- (Taicpu(hp1).oper[0]^.val=1)
- ) then
- carryadd_opcode:=A_ADC;
- if (Taicpu(hp1).opcode=A_DEC) or
- ((Taicpu(hp1).opcode=A_SUB) and
- MatchOptype(Taicpu(hp1),top_const,top_reg) and
- (Taicpu(hp1).oper[0]^.val=1)
- ) then
- carryadd_opcode:=A_SBB;
- if carryadd_opcode<>A_NONE then
- begin
- Taicpu(p).clearop(0);
- Taicpu(p).ops:=0;
- Taicpu(p).is_jmp:=false;
- Taicpu(p).opcode:=A_CMC;
- Taicpu(p).condition:=C_NONE;
- DebugMsg(SPeepholeOptimization+'JccAdd/Inc/Dec2CmcAdc/Sbb',p);
- Taicpu(hp1).ops:=2;
- if (Taicpu(hp1).opcode=A_ADD) or (Taicpu(hp1).opcode=A_SUB) then
- Taicpu(hp1).loadoper(1,Taicpu(hp1).oper[1]^)
- else
- Taicpu(hp1).loadoper(1,Taicpu(hp1).oper[0]^);
- Taicpu(hp1).loadconst(0,0);
- Taicpu(hp1).opcode:=carryadd_opcode;
- result:=true;
- exit;
- end;
+ case taicpu(hp1).opcode of
+ A_INC,
+ A_ADD:
+ carryadd_opcode:=A_ADC;
+ A_DEC,
+ A_SUB:
+ carryadd_opcode:=A_SBB;
+ else
+ InternalError(2021011001);
+ end;
+
+ Taicpu(p).clearop(0);
+ Taicpu(p).ops:=0;
+ Taicpu(p).is_jmp:=false;
+ Taicpu(p).opcode:=A_CMC;
+ Taicpu(p).condition:=C_NONE;
+ DebugMsg(SPeepholeOptimization+'JccAdd/Inc/Dec2CmcAdc/Sbb',p);
+ Taicpu(hp1).ops:=2;
+ if (Taicpu(hp1).opcode=A_ADD) or (Taicpu(hp1).opcode=A_SUB) then
+ Taicpu(hp1).loadoper(1,Taicpu(hp1).oper[1]^)
+ else
+ Taicpu(hp1).loadoper(1,Taicpu(hp1).oper[0]^);
+ Taicpu(hp1).loadconst(0,0);
+ Taicpu(hp1).opcode:=carryadd_opcode;
+ result:=true;
+ exit;
end
else if Taicpu(p).condition in [C_AE,C_NB,C_NC] then
begin
- if (Taicpu(hp1).opcode=A_INC) or
- ((Taicpu(hp1).opcode=A_ADD) and
- MatchOptype(Taicpu(hp1),top_const,top_reg) and
- (Taicpu(hp1).oper[0]^.val=1)
- ) then
- carryadd_opcode:=A_ADC;
- if (Taicpu(hp1).opcode=A_DEC) or
- ((Taicpu(hp1).opcode=A_SUB) and
- MatchOptype(Taicpu(hp1),top_const,top_reg) and
- (Taicpu(hp1).oper[0]^.val=1)
- ) then
- carryadd_opcode:=A_SBB;
- if carryadd_opcode<>A_NONE then
- begin
- Taicpu(hp1).ops:=2;
- DebugMsg(SPeepholeOptimization+'JccAdd/Inc/Dec2Adc/Sbb',p);
- if (Taicpu(hp1).opcode=A_ADD) or (Taicpu(hp1).opcode=A_SUB) then
- Taicpu(hp1).loadoper(1,Taicpu(hp1).oper[1]^)
- else
- Taicpu(hp1).loadoper(1,Taicpu(hp1).oper[0]^);
- Taicpu(hp1).loadconst(0,0);
- Taicpu(hp1).opcode:=carryadd_opcode;
- RemoveCurrentP(p, hp1);
- result:=true;
- exit;
- end;
+ case taicpu(hp1).opcode of
+ A_INC,
+ A_ADD:
+ carryadd_opcode:=A_ADC;
+ A_DEC,
+ A_SUB:
+ carryadd_opcode:=A_SBB;
+ else
+ InternalError(2021011002);
+ end;
+
+ Taicpu(hp1).ops:=2;
+ DebugMsg(SPeepholeOptimization+'JccAdd/Inc/Dec2Adc/Sbb',p);
+ if (Taicpu(hp1).opcode=A_ADD) or (Taicpu(hp1).opcode=A_SUB) then
+ Taicpu(hp1).loadoper(1,Taicpu(hp1).oper[1]^)
+ else
+ Taicpu(hp1).loadoper(1,Taicpu(hp1).oper[0]^);
+ Taicpu(hp1).loadconst(0,0);
+ Taicpu(hp1).opcode:=carryadd_opcode;
+ RemoveCurrentP(p, hp1);
+ result:=true;
+ exit;
end
{
jcc @@1 setcc tmpreg
@@ -5742,312 +5784,323 @@ unit aoptx86;
While this increases code size slightly, it makes the code much faster if the
jump is unpredictable
}
- else if not(cs_opt_size in current_settings.optimizerswitches) and
- ((((Taicpu(hp1).opcode=A_ADD) or (Taicpu(hp1).opcode=A_SUB)) and
- (Taicpu(hp1).oper[0]^.typ=top_const) and
- (Taicpu(hp1).oper[1]^.typ=top_reg) and
- (Taicpu(hp1).oper[0]^.val=1)) or
- ((Taicpu(hp1).opcode=A_INC) or (Taicpu(hp1).opcode=A_DEC))
- ) then
- begin
- TransferUsedRegs(TmpUsedRegs);
- UpdateUsedRegs(TmpUsedRegs, tai(p.next));
-
- { search for an available register which is volatile }
- regavailable:=false;
- for reg in tcpuregisterset do
- begin
- if (reg in paramanager.get_volatile_registers_int(current_procinfo.procdef.proccalloption)) and
- not(reg in TmpUsedRegs[R_INTREGISTER].GetUsedRegs) and
- not(RegInInstruction(newreg(R_INTREGISTER,reg,R_SUBL),hp1))
-{$ifdef i386}
- and (reg in [RS_EAX,RS_EBX,RS_ECX,RS_EDX])
-{$endif i386}
- then
- begin
- regavailable:=true;
- break;
- end;
- end;
-
- if regavailable then
- begin
- Taicpu(p).clearop(0);
- Taicpu(p).ops:=1;
- Taicpu(p).is_jmp:=false;
- Taicpu(p).opcode:=A_SETcc;
- DebugMsg(SPeepholeOptimization+'JccAdd2SetccAdd',p);
- Taicpu(p).condition:=inverse_cond(Taicpu(p).condition);
- Taicpu(p).loadreg(0,newreg(R_INTREGISTER,reg,R_SUBL));
-
- if getsubreg(Taicpu(hp1).oper[1]^.reg)<>R_SUBL then
- begin
- case getsubreg(Taicpu(hp1).oper[1]^.reg) of
- R_SUBW:
- hp2:=Taicpu.op_reg_reg(A_MOVZX,S_BW,newreg(R_INTREGISTER,reg,R_SUBL),
- newreg(R_INTREGISTER,reg,R_SUBW));
- R_SUBD,
- R_SUBQ:
- hp2:=Taicpu.op_reg_reg(A_MOVZX,S_BL,newreg(R_INTREGISTER,reg,R_SUBL),
- newreg(R_INTREGISTER,reg,R_SUBD));
- else
- Internalerror(2020030601);
- end;
- taicpu(hp2).fileinfo:=taicpu(hp1).fileinfo;
- asml.InsertAfter(hp2,p);
- end;
- if (Taicpu(hp1).opcode=A_INC) or (Taicpu(hp1).opcode=A_DEC) then
- begin
- Taicpu(hp1).ops:=2;
- Taicpu(hp1).loadoper(1,Taicpu(hp1).oper[0]^)
- end;
- Taicpu(hp1).loadreg(0,newreg(R_INTREGISTER,reg,getsubreg(Taicpu(hp1).oper[1]^.reg)));
- AllocRegBetween(newreg(R_INTREGISTER,reg,getsubreg(Taicpu(hp1).oper[1]^.reg)),p,hp1,UsedRegs);
- end;
- end;
- end;
+ else if not(cs_opt_size in current_settings.optimizerswitches) then
+ begin
+ { search for an available register which is volatile }
+ for reg in tcpuregisterset do
+ begin
+ if
+ {$if defined(i386) or defined(i8086)}
+ { Only use registers whose lowest 8-bits can Be accessed }
+ (reg in [RS_EAX,RS_EBX,RS_ECX,RS_EDX]) and
+ {$endif i386 or i8086}
+ (reg in paramanager.get_volatile_registers_int(current_procinfo.procdef.proccalloption)) and
+ not(reg in UsedRegs[R_INTREGISTER].GetUsedRegs)
+ { We don't need to check if tmpreg is in hp1 or not, because
+ it will be marked as in use at p (if not, this is
+ indictive of a compiler bug). }
+ then
+ begin
+ TAsmLabel(symbol).decrefs;
+ increg := newreg(R_INTREGISTER,reg,R_SUBL);
+ Taicpu(p).clearop(0);
+ Taicpu(p).ops:=1;
+ Taicpu(p).is_jmp:=false;
+ Taicpu(p).opcode:=A_SETcc;
+ DebugMsg(SPeepholeOptimization+'JccAdd2SetccAdd',p);
+ Taicpu(p).condition:=inverse_cond(Taicpu(p).condition);
+ Taicpu(p).loadreg(0,increg);
+
+ if getsubreg(Taicpu(hp1).oper[1]^.reg)<>R_SUBL then
+ begin
+ case getsubreg(Taicpu(hp1).oper[1]^.reg) of
+ R_SUBW:
+ begin
+ tmpreg := newreg(R_INTREGISTER,reg,R_SUBW);
+ hp2:=Taicpu.op_reg_reg(A_MOVZX,S_BW,increg,tmpreg);
+ end;
+ R_SUBD:
+ begin
+ tmpreg := newreg(R_INTREGISTER,reg,R_SUBD);
+ hp2:=Taicpu.op_reg_reg(A_MOVZX,S_BL,increg,tmpreg);
+ end;
+ {$ifdef x86_64}
+ R_SUBQ:
+ begin
+ { MOVZX doesn't have a 64-bit variant, because
+ the 32-bit version implicitly zeroes the
+ upper 32-bits of the destination register }
+ hp2:=Taicpu.op_reg_reg(A_MOVZX,S_BL,increg,
+ newreg(R_INTREGISTER,reg,R_SUBD));
+ tmpreg := newreg(R_INTREGISTER,reg,R_SUBQ);
+ end;
+ {$endif x86_64}
+ else
+ Internalerror(2020030601);
+ end;
+ taicpu(hp2).fileinfo:=taicpu(hp1).fileinfo;
+ asml.InsertAfter(hp2,p);
+ end
+ else
+ tmpreg := increg;
+
+ if (Taicpu(hp1).opcode=A_INC) or (Taicpu(hp1).opcode=A_DEC) then
+ begin
+ Taicpu(hp1).ops:=2;
+ Taicpu(hp1).loadoper(1,Taicpu(hp1).oper[0]^)
+ end;
+ Taicpu(hp1).loadreg(0,tmpreg);
+ AllocRegBetween(tmpreg,p,hp1,UsedRegs);
+
+ Result := True;
+
+ { p is no longer a Jcc instruction, so exit }
+ Exit;
+ end;
+ end;
+ end;
+ end;
- { Detect the following:
- jmp<cond> @Lbl1
- jmp @Lbl2
- ...
- @Lbl1:
- ret
+ { Detect the following:
+ jmp<cond> @Lbl1
+ jmp @Lbl2
+ ...
+ @Lbl1:
+ ret
- Change to:
+ Change to:
- jmp<inv_cond> @Lbl2
- ret
- }
- if MatchInstruction(hp1,A_JMP,[]) and (taicpu(hp1).oper[0]^.ref^.refaddr=addr_full) then
- begin
- hp2:=getlabelwithsym(TAsmLabel(symbol));
- if Assigned(hp2) and SkipLabels(hp2,hp2) and
- MatchInstruction(hp2,A_RET,[S_NO]) then
- begin
- taicpu(p).condition := inverse_cond(taicpu(p).condition);
-
- { Change label address to that of the unconditional jump }
- taicpu(p).loadoper(0, taicpu(hp1).oper[0]^);
-
- TAsmLabel(symbol).DecRefs;
- taicpu(hp1).opcode := A_RET;
- taicpu(hp1).is_jmp := false;
- taicpu(hp1).ops := taicpu(hp2).ops;
- DebugMsg(SPeepholeOptimization+'JccJmpRet2J!ccRet',p);
- case taicpu(hp2).ops of
- 0:
- taicpu(hp1).clearop(0);
- 1:
- taicpu(hp1).loadconst(0,taicpu(hp2).oper[0]^.val);
- else
- internalerror(2016041302);
+ jmp<inv_cond> @Lbl2
+ ret
+ }
+ if MatchInstruction(hp1,A_JMP,[]) and (taicpu(hp1).oper[0]^.ref^.refaddr=addr_full) then
+ begin
+ hp2:=getlabelwithsym(TAsmLabel(symbol));
+ if Assigned(hp2) and SkipLabels(hp2,hp2) and
+ MatchInstruction(hp2,A_RET,[S_NO]) then
+ begin
+ taicpu(p).condition := inverse_cond(taicpu(p).condition);
+
+ { Change label address to that of the unconditional jump }
+ taicpu(p).loadoper(0, taicpu(hp1).oper[0]^);
+
+ TAsmLabel(symbol).DecRefs;
+ taicpu(hp1).opcode := A_RET;
+ taicpu(hp1).is_jmp := false;
+ taicpu(hp1).ops := taicpu(hp2).ops;
+ DebugMsg(SPeepholeOptimization+'JccJmpRet2J!ccRet',p);
+ case taicpu(hp2).ops of
+ 0:
+ taicpu(hp1).clearop(0);
+ 1:
+ taicpu(hp1).loadconst(0,taicpu(hp2).oper[0]^.val);
+ else
+ internalerror(2016041302);
+ end;
end;
- end;
- end;
- end;
{$ifndef i8086}
- if CPUX86_HAS_CMOV in cpu_capabilities[current_settings.cputype] then
- begin
- { check for
- jCC xxx
- <several movs>
- xxx:
- }
- l:=0;
- GetNextInstruction(p, hp1);
- while assigned(hp1) and
- CanBeCMOV(hp1) and
- { stop on labels }
- not(hp1.typ=ait_label) do
- begin
- inc(l);
- GetNextInstruction(hp1,hp1);
- end;
- if assigned(hp1) then
- begin
- if FindLabel(tasmlabel(symbol),hp1) then
- begin
- if (l<=4) and (l>0) then
+ end
+ else if CPUX86_HAS_CMOV in cpu_capabilities[current_settings.cputype] then
+ begin
+ { check for
+ jCC xxx
+ <several movs>
+ xxx:
+ }
+ l:=0;
+ while assigned(hp1) and
+ CanBeCMOV(hp1) and
+ { stop on labels }
+ not(hp1.typ=ait_label) do
+ begin
+ inc(l);
+ GetNextInstruction(hp1,hp1);
+ end;
+ if assigned(hp1) then
+ begin
+ if FindLabel(tasmlabel(symbol),hp1) then
begin
- condition:=inverse_cond(taicpu(p).condition);
- GetNextInstruction(p,hp1);
- repeat
- if not Assigned(hp1) then
- InternalError(2018062900);
-
- taicpu(hp1).opcode:=A_CMOVcc;
- taicpu(hp1).condition:=condition;
- UpdateUsedRegs(hp1);
- GetNextInstruction(hp1,hp1);
- until not(CanBeCMOV(hp1));
-
- { Remember what hp1 is in case there's multiple aligns to get rid of }
- hp2 := hp1;
- repeat
- if not Assigned(hp2) then
- InternalError(2018062910);
-
- case hp2.typ of
- ait_label:
- { What we expected - break out of the loop (it won't be a dead label at the top of
- a cluster because that was optimised at an earlier stage) }
- Break;
- ait_align:
- { Go to the next entry until a label is found (may be multiple aligns before it) }
- begin
- hp2 := tai(hp2.Next);
- Continue;
- end;
- else
- begin
- { Might be a comment or temporary allocation entry }
- if not (hp2.typ in SkipInstr) then
- InternalError(2018062911);
+ if (l<=4) and (l>0) then
+ begin
+ condition:=inverse_cond(taicpu(p).condition);
+ GetNextInstruction(p,hp1);
+ repeat
+ if not Assigned(hp1) then
+ InternalError(2018062900);
+
+ taicpu(hp1).opcode:=A_CMOVcc;
+ taicpu(hp1).condition:=condition;
+ UpdateUsedRegs(hp1);
+ GetNextInstruction(hp1,hp1);
+ until not(CanBeCMOV(hp1));
+
+ { Remember what hp1 is in case there's multiple aligns to get rid of }
+ hp2 := hp1;
+ repeat
+ if not Assigned(hp2) then
+ InternalError(2018062910);
+
+ case hp2.typ of
+ ait_label:
+ { What we expected - break out of the loop (it won't be a dead label at the top of
+ a cluster because that was optimised at an earlier stage) }
+ Break;
+ ait_align:
+ { Go to the next entry until a label is found (may be multiple aligns before it) }
+ begin
+ hp2 := tai(hp2.Next);
+ Continue;
+ end;
+ else
+ begin
+ { Might be a comment or temporary allocation entry }
+ if not (hp2.typ in SkipInstr) then
+ InternalError(2018062911);
- hp2 := tai(hp2.Next);
- Continue;
+ hp2 := tai(hp2.Next);
+ Continue;
+ end;
end;
- end;
- until False;
+ until False;
- { Now we can safely decrement the reference count }
- tasmlabel(symbol).decrefs;
+ { Now we can safely decrement the reference count }
+ tasmlabel(symbol).decrefs;
- DebugMsg(SPeepholeOptimization+'JccMov2CMov',p);
+ DebugMsg(SPeepholeOptimization+'JccMov2CMov',p);
- { Remove the original jump }
- RemoveInstruction(p); { Note, the choice to not use RemoveCurrentp is deliberate }
+ { Remove the original jump }
+ RemoveInstruction(p); { Note, the choice to not use RemoveCurrentp is deliberate }
- GetNextInstruction(hp2, p); { Instruction after the label }
+ GetNextInstruction(hp2, p); { Instruction after the label }
- { Remove the label if this is its final reference }
- if (tasmlabel(symbol).getrefs=0) then
- StripLabelFast(hp1);
+ { Remove the label if this is its final reference }
+ if (tasmlabel(symbol).getrefs=0) then
+ StripLabelFast(hp1);
- if Assigned(p) then
- begin
- UpdateUsedRegs(p);
- result:=true;
+ if Assigned(p) then
+ begin
+ UpdateUsedRegs(p);
+ result:=true;
+ end;
+ exit;
end;
- exit;
- end;
- end
- else
- begin
- { check further for
- jCC xxx
- <several movs 1>
- jmp yyy
- xxx:
- <several movs 2>
- yyy:
- }
- { hp2 points to jmp yyy }
- hp2:=hp1;
- { skip hp1 to xxx (or an align right before it) }
- GetNextInstruction(hp1, hp1);
-
- if assigned(hp2) and
- assigned(hp1) and
- (l<=3) and
- (hp2.typ=ait_instruction) and
- (taicpu(hp2).is_jmp) and
- (taicpu(hp2).condition=C_None) and
- { real label and jump, no further references to the
- label are allowed }
- (tasmlabel(symbol).getrefs=1) and
- FindLabel(tasmlabel(symbol),hp1) then
- begin
- l:=0;
- { skip hp1 to <several moves 2> }
- if (hp1.typ = ait_align) then
- GetNextInstruction(hp1, hp1);
-
- GetNextInstruction(hp1, hpmov2);
-
- hp1 := hpmov2;
- while assigned(hp1) and
- CanBeCMOV(hp1) do
- begin
- inc(l);
- GetNextInstruction(hp1, hp1);
- end;
- { hp1 points to yyy (or an align right before it) }
- hp3 := hp1;
- if assigned(hp1) and
- FindLabel(tasmlabel(taicpu(hp2).oper[0]^.ref^.symbol),hp1) then
+ end
+ else
+ begin
+ { check further for
+ jCC xxx
+ <several movs 1>
+ jmp yyy
+ xxx:
+ <several movs 2>
+ yyy:
+ }
+ { hp2 points to jmp yyy }
+ hp2:=hp1;
+ { skip hp1 to xxx (or an align right before it) }
+ GetNextInstruction(hp1, hp1);
+
+ if assigned(hp2) and
+ assigned(hp1) and
+ (l<=3) and
+ (hp2.typ=ait_instruction) and
+ (taicpu(hp2).is_jmp) and
+ (taicpu(hp2).condition=C_None) and
+ { real label and jump, no further references to the
+ label are allowed }
+ (tasmlabel(symbol).getrefs=1) and
+ FindLabel(tasmlabel(symbol),hp1) then
begin
- condition:=inverse_cond(taicpu(p).condition);
- GetNextInstruction(p,hp1);
- repeat
- taicpu(hp1).opcode:=A_CMOVcc;
- taicpu(hp1).condition:=condition;
- UpdateUsedRegs(hp1);
- GetNextInstruction(hp1,hp1);
- until not(assigned(hp1)) or
- not(CanBeCMOV(hp1));
-
- condition:=inverse_cond(condition);
- hp1 := hpmov2;
- { hp1 is now at <several movs 2> }
- while Assigned(hp1) and CanBeCMOV(hp1) do
- begin
- taicpu(hp1).opcode:=A_CMOVcc;
- taicpu(hp1).condition:=condition;
- UpdateUsedRegs(hp1);
- GetNextInstruction(hp1,hp1);
- end;
+ l:=0;
+ { skip hp1 to <several moves 2> }
+ if (hp1.typ = ait_align) then
+ GetNextInstruction(hp1, hp1);
+
+ GetNextInstruction(hp1, hpmov2);
+
+ hp1 := hpmov2;
+ while assigned(hp1) and
+ CanBeCMOV(hp1) do
+ begin
+ inc(l);
+ GetNextInstruction(hp1, hp1);
+ end;
+ { hp1 points to yyy (or an align right before it) }
+ hp3 := hp1;
+ if assigned(hp1) and
+ FindLabel(tasmlabel(taicpu(hp2).oper[0]^.ref^.symbol),hp1) then
+ begin
+ condition:=inverse_cond(taicpu(p).condition);
+ GetNextInstruction(p,hp1);
+ repeat
+ taicpu(hp1).opcode:=A_CMOVcc;
+ taicpu(hp1).condition:=condition;
+ UpdateUsedRegs(hp1);
+ GetNextInstruction(hp1,hp1);
+ until not(assigned(hp1)) or
+ not(CanBeCMOV(hp1));
+
+ condition:=inverse_cond(condition);
+ hp1 := hpmov2;
+ { hp1 is now at <several movs 2> }
+ while Assigned(hp1) and CanBeCMOV(hp1) do
+ begin
+ taicpu(hp1).opcode:=A_CMOVcc;
+ taicpu(hp1).condition:=condition;
+ UpdateUsedRegs(hp1);
+ GetNextInstruction(hp1,hp1);
+ end;
- hp1 := p;
+ hp1 := p;
- { Get first instruction after label }
- GetNextInstruction(hp3, p);
+ { Get first instruction after label }
+ GetNextInstruction(hp3, p);
- if assigned(p) and (hp3.typ = ait_align) then
- GetNextInstruction(p, p);
+ if assigned(p) and (hp3.typ = ait_align) then
+ GetNextInstruction(p, p);
- { Don't dereference yet, as doing so will cause
- GetNextInstruction to skip the label and
- optional align marker. [Kit] }
- GetNextInstruction(hp2, hp4);
+ { Don't dereference yet, as doing so will cause
+ GetNextInstruction to skip the label and
+ optional align marker. [Kit] }
+ GetNextInstruction(hp2, hp4);
- DebugMsg(SPeepholeOptimization+'JccMovJmpMov2CMovCMov',hp1);
+ DebugMsg(SPeepholeOptimization+'JccMovJmpMov2CMovCMov',hp1);
- { remove jCC }
- RemoveInstruction(hp1);
+ { remove jCC }
+ RemoveInstruction(hp1);
- { Now we can safely decrement it }
- tasmlabel(symbol).decrefs;
+ { Now we can safely decrement it }
+ tasmlabel(symbol).decrefs;
- { Remove label xxx (it will have a ref of zero due to the initial check }
- StripLabelFast(hp4);
+ { Remove label xxx (it will have a ref of zero due to the initial check }
+ StripLabelFast(hp4);
- { remove jmp }
- symbol := taicpu(hp2).oper[0]^.ref^.symbol;
+ { remove jmp }
+ symbol := taicpu(hp2).oper[0]^.ref^.symbol;
- RemoveInstruction(hp2);
+ RemoveInstruction(hp2);
- { As before, now we can safely decrement it }
- tasmlabel(symbol).decrefs;
+ { As before, now we can safely decrement it }
+ tasmlabel(symbol).decrefs;
- { Remove label yyy (and the optional alignment) if its reference falls to zero }
- if tasmlabel(symbol).getrefs = 0 then
- StripLabelFast(hp3);
+ { Remove label yyy (and the optional alignment) if its reference falls to zero }
+ if tasmlabel(symbol).getrefs = 0 then
+ StripLabelFast(hp3);
- if Assigned(p) then
- begin
- UpdateUsedRegs(p);
- result:=true;
- end;
- exit;
+ if Assigned(p) then
+ begin
+ UpdateUsedRegs(p);
+ result:=true;
+ end;
+ exit;
+ end;
end;
- end;
- end;
- end;
- end;
+ end;
+ end;
{$endif i8086}
+ end;
+ end;
end;
@@ -7016,12 +7069,14 @@ unit aoptx86;
function TX86AsmOptimizer.PostPeepholeOptPush(var p : tai) : Boolean;
+{$ifdef x86_64}
var
hp1, hp2, hp3, hp4, hp5: tai;
+{$endif x86_64}
begin
Result:=false;
- hp5:=nil;
{$ifdef x86_64}
+ hp5:=nil;
{ replace
push %rax
call procname
@@ -7476,7 +7531,8 @@ unit aoptx86;
(taicpu(hp1).opcode = A_TEST) and MatchOperand(taicpu(hp1).oper[0]^, taicpu(hp1).oper[1]^)
)
) and
- (reg2opsize(taicpu(hp1).oper[1]^.reg) <= reg2opsize(taicpu(p).oper[1]^.reg)) then
+ (reg2opsize(taicpu(hp1).oper[1]^.reg) <= reg2opsize(taicpu(p).oper[1]^.reg)) and
+ SuperRegistersEqual(taicpu(p).oper[1]^.reg, taicpu(hp1).oper[1]^.reg) then
begin
PreMessage := debug_op2str(taicpu(hp1).opcode) + debug_opsize2str(taicpu(hp1).opsize) + ' ' + debug_operstr(taicpu(hp1).oper[0]^) + ',' + debug_regname(taicpu(hp1).oper[1]^.reg) + ' -> ' + debug_op2str(taicpu(hp1).opcode);
diff --git a/avx512-0037785/compiler/x86/cgx86.pas b/avx512-0037785/compiler/x86/cgx86.pas
index b270ddd59d..a790ccac4f 100644
--- a/avx512-0037785/compiler/x86/cgx86.pas
+++ b/avx512-0037785/compiler/x86/cgx86.pas
@@ -445,13 +445,17 @@ unit cgx86;
procedure tcgx86.make_simple_ref(list:TAsmList;var ref: treference;isdirect:boolean);
var
+{$ifndef i8086}
hreg : tregister;
+{$endif i8086}
href : treference;
-{$ifndef x86_64}
+{$ifdef i386}
add_hreg: boolean;
-{$endif not x86_64}
+{$endif i386}
begin
+{$ifndef i8086}
hreg:=NR_NO;
+{$endif i8086}
{ make_simple_ref() may have already been called earlier, and in that
case make sure we don't perform the PIC-simplifications twice }
if (ref.refaddr in [addr_pic,addr_pic_no_got]) then
@@ -1083,7 +1087,9 @@ unit cgx86;
procedure tcgx86.a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);
var
dirref,tmpref : treference;
+{$ifndef i8086}
tmpreg : TRegister;
+{$endif i8086}
begin
dirref:=ref;
@@ -1995,7 +2001,7 @@ unit cgx86;
href.scalefactor:=a;
list.concat(taicpu.op_ref_reg(A_LEA,TCgSize2OpSize[size],href,dst));
end
- else if (op in [OP_MUL,OP_IMUL]) and (size in [OS_32,OS_S32,OS_64,OS_S64]) and
+ else if (op in [OP_MUL,OP_IMUL]) and (size in [OS_16,OS_S16,OS_32,OS_S32,OS_64,OS_S64]) and
(a>1) and (a<=maxLongint) and not ispowerof2(int64(a),power) then
begin
{ MUL with overflow checking should be handled specifically in the code generator }
@@ -2343,6 +2349,17 @@ unit cgx86;
begin
if reg2opsize(src) <> dstsize then
internalerror(200109226);
+ { x86 does not have an 8 Bit imul, so do 16 Bit multiplication
+ we do not need to zero/sign extend as we discard the upper bits anyways }
+ if (TOpCG2AsmOp[op]=A_IMUL) and (size in [OS_8,OS_S8]) then
+ begin
+ { this might only happen if no overflow checking is done }
+ if cs_check_overflow in current_settings.localswitches then
+ Internalerror(2021011601);
+ src:=makeregsize(list,src,OS_16);
+ dst:=makeregsize(list,dst,OS_16);
+ dstsize:=S_W;
+ end;
instr:=taicpu.op_reg_reg(TOpCG2AsmOp[op],dstsize,src,dst);
list.concat(instr);
end;
@@ -3220,10 +3237,12 @@ unit cgx86;
{$ifdef x86}
{$ifndef NOTARGETWIN}
+{$ifndef i8086}
var
href : treference;
i : integer;
again : tasmlabel;
+{$endif i8086}
{$endif NOTARGETWIN}
{$endif x86}
begin
diff --git a/avx512-0037785/compiler/x86/cx86mminnr.inc b/avx512-0037785/compiler/x86/cx86mminnr.inc
index f4684e66c1..6d2717f644 100644
--- a/avx512-0037785/compiler/x86/cx86mminnr.inc
+++ b/avx512-0037785/compiler/x86/cx86mminnr.inc
@@ -499,5 +499,5 @@
in_x86_pcmpistrm = in_x86_mm_first+498,
in_x86_pcmpistrm_from_mem = in_x86_mm_first+499,
in_x86_pcmpgtq = in_x86_mm_first+500,
- in_x86_pcmpgtq_from_mem = in_x86_mm_first+501,
- in_x86mm_last = in_x86_mm_first+501
+ in_x86_pcmpgtq_from_mem = in_x86_mm_first+501
+
diff --git a/avx512-0037785/compiler/x86/nx86inl.pas b/avx512-0037785/compiler/x86/nx86inl.pas
index 1b9c174d44..c26cbd5a32 100644
--- a/avx512-0037785/compiler/x86/nx86inl.pas
+++ b/avx512-0037785/compiler/x86/nx86inl.pas
@@ -1144,6 +1144,7 @@ implementation
procedure tx86inlinenode.second_fma;
+{$ifndef i8086}
const
op : array[false..true,false..true,s32real..s64real,0..3] of TAsmOp =
(
@@ -1178,6 +1179,7 @@ implementation
negop3,
negproduct,
gotmem : boolean;
+{$endif i8086}
begin
{$ifndef i8086}
if (cpu_capabilities[current_settings.cputype]*[CPUX86_HAS_FMA,CPUX86_HAS_FMA4])<>[] then
@@ -1444,6 +1446,7 @@ implementation
procedure tx86inlinenode.second_minmax;
+{$ifndef i8086}
const
oparray : array[false..true,false..true,s32real..s64real] of TAsmOp =
(
@@ -1463,6 +1466,7 @@ implementation
i : integer;
gotmem : boolean;
op: TAsmOp;
+{$endif i8086}
begin
{$ifndef i8086}
if
diff --git a/avx512-0037785/compiler/x86/nx86mat.pas b/avx512-0037785/compiler/x86/nx86mat.pas
index 036fb2dc67..19359e2e0a 100644
--- a/avx512-0037785/compiler/x86/nx86mat.pas
+++ b/avx512-0037785/compiler/x86/nx86mat.pas
@@ -164,10 +164,6 @@ interface
procedure tx86unaryminusnode.second_float;
- var
- reg : tregister;
- href : treference;
- l1 : tasmlabel;
begin
secondpass(left);
@@ -387,7 +383,10 @@ interface
cgsize:=def_cgsize(resultdef);
opsize:=TCGSize2OpSize[cgsize];
rega:=newreg(R_INTREGISTER,RS_EAX,cgsize2subreg(R_INTREGISTER,cgsize));
- regd:=newreg(R_INTREGISTER,RS_EDX,cgsize2subreg(R_INTREGISTER,cgsize));
+ if cgsize in [OS_8,OS_S8] then
+ regd:=NR_AH
+ else
+ regd:=newreg(R_INTREGISTER,RS_EDX,cgsize2subreg(R_INTREGISTER,cgsize));
location_reset(location,LOC_REGISTER,cgsize);
hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,resultdef,false);
diff --git a/avx512-0037785/compiler/x86/nx86set.pas b/avx512-0037785/compiler/x86/nx86set.pas
index 001ba0fc40..c0caf10b19 100644
--- a/avx512-0037785/compiler/x86/nx86set.pas
+++ b/avx512-0037785/compiler/x86/nx86set.pas
@@ -420,7 +420,7 @@ implementation
start,stop : byte; {Start/stop when range; Stop=element when an element.}
end;
var
- hreg,hreg2,
+ hreg,{$ifndef i8086} hreg2, {$endif}
pleftreg : tregister;
opsize : tcgsize;
opdef : torddef;
diff --git a/avx512-0037785/compiler/x86/rax86.pas b/avx512-0037785/compiler/x86/rax86.pas
index 0c077535c2..a0cfa731a0 100644
--- a/avx512-0037785/compiler/x86/rax86.pas
+++ b/avx512-0037785/compiler/x86/rax86.pas
@@ -1617,8 +1617,6 @@ procedure Tx86Instruction.SetInstructionOpsize;
end;
end;
-var
- isBCastMemRef: boolean;
begin
if opsize<>S_NO then
exit;
diff --git a/avx512-0037785/compiler/x86_64/aoptcpu.pas b/avx512-0037785/compiler/x86_64/aoptcpu.pas
index 5ac6583fd5..0829a8b9c4 100644
--- a/avx512-0037785/compiler/x86_64/aoptcpu.pas
+++ b/avx512-0037785/compiler/x86_64/aoptcpu.pas
@@ -71,6 +71,8 @@ uses
ait_instruction:
begin
case taicpu(p).opcode of
+ A_ADD:
+ Result:=OptPass1ADD(p);
A_AND:
Result:=OptPass1AND(p);
A_IMUL:
diff --git a/avx512-0037785/compiler/x86_64/cpuelf.pas b/avx512-0037785/compiler/x86_64/cpuelf.pas
index 7c7dc3cdf0..dfea338a74 100644
--- a/avx512-0037785/compiler/x86_64/cpuelf.pas
+++ b/avx512-0037785/compiler/x86_64/cpuelf.pas
@@ -88,6 +88,8 @@ implementation
R_X86_64_TLSDESC_CALL = 35;
R_X86_64_TLSDESC = 36;
R_X86_64_IRELATIVE = 37;
+ R_X86_64_GOTPCRELX =41;
+ R_X86_64_REX_GOTPCRELX =42;
R_X86_64_GNU_VTINHERIT = 250; { GNU extension to record C++ vtable hierarchy }
R_X86_64_GNU_VTENTRY = 251; { GNU extension to record C++ vtable member usage }
@@ -169,6 +171,10 @@ implementation
result:=R_X86_64_32S;
RELOC_GOTPCREL :
result:=R_X86_64_GOTPCREL;
+ RELOC_GOTPCRELX :
+ result:=R_X86_64_GOTPCRELX;
+ RELOC_REX_GOTPCRELX :
+ result:=R_X86_64_REX_GOTPCRELX;
RELOC_PLT32 :
result:=R_X86_64_PLT32;
RELOC_TPOFF:
diff --git a/avx512-0037785/compiler/x86_64/cpupara.pas b/avx512-0037785/compiler/x86_64/cpupara.pas
index 7bbb48580c..b35b0a2331 100644
--- a/avx512-0037785/compiler/x86_64/cpupara.pas
+++ b/avx512-0037785/compiler/x86_64/cpupara.pas
@@ -178,10 +178,13 @@ unit cpupara;
cl.typ:=X86_64_INTEGERSI_CLASS;
{ gcc/clang sign/zero-extend all values to 32 bits, except for
_Bool (= Pascal boolean), which is only zero-extended to 8 bits
- as per the x86-64 ABI -> do the same }
+ as per the x86-64 ABI -> do the same
+
+ some testing showed, that this is not true for 8 bit values:
+ in case of an 8 bit value, it is not zero/sign extended }
if not assigned(cl.def) or
- not is_pasbool(cl.def) or
- (torddef(cl.def).ordtype<>pasbool1) then
+ not(cl.def.typ=orddef) or
+ not(torddef(cl.def).ordtype in [uchar,u8bit,s8bit,pasbool1]) then
cl.def:=u32inttype;
end
else
diff --git a/avx512-0037785/compiler/x86_64/nx64mat.pas b/avx512-0037785/compiler/x86_64/nx64mat.pas
index 8400bee676..74731bccac 100644
--- a/avx512-0037785/compiler/x86_64/nx64mat.pas
+++ b/avx512-0037785/compiler/x86_64/nx64mat.pas
@@ -43,6 +43,7 @@ implementation
uses
globtype,constexp,
+ cutils,
aasmdata,defutil,
pass_2,
ncon,
@@ -69,24 +70,8 @@ implementation
else
op:=OP_SHR;
- { special treatment of 32bit values for backwards compatibility }
- { mul optimizations require to keep the sign (FK) }
- if left.resultdef.size<=4 then
- begin
- if is_signed(left.resultdef) then
- opsize:=OS_S32
- else
- opsize:=OS_32;
- mask:=31;
- end
- else
- begin
- if is_signed(left.resultdef) then
- opsize:=OS_S64
- else
- opsize:=OS_64;
- mask:=63;
- end;
+ opsize:=def_cgsize(resultdef);
+ mask:=max(resultdef.size,4)*8-1;
{ load left operators in a register }
if not(left.location.loc in [LOC_CREGISTER,LOC_REGISTER]) or
diff --git a/avx512-0037785/packages/fcl-base/src/bufstream.pp b/avx512-0037785/packages/fcl-base/src/bufstream.pp
index 81ae8d377a..2517542e97 100644
--- a/avx512-0037785/packages/fcl-base/src/bufstream.pp
+++ b/avx512-0037785/packages/fcl-base/src/bufstream.pp
@@ -812,7 +812,7 @@ begin
lNewOffset:=FCacheStreamPosition+Offset;
end;
end;
- if lNewOffset>0 then begin
+ if lNewOffset>=0 then begin
FCacheStreamPosition:=lNewOffset;
Result:=lNewOffset;
end else begin
diff --git a/avx512-0037785/packages/fcl-base/src/eventlog.pp b/avx512-0037785/packages/fcl-base/src/eventlog.pp
index a72bbd1f93..24492b54ea 100644
--- a/avx512-0037785/packages/fcl-base/src/eventlog.pp
+++ b/avx512-0037785/packages/fcl-base/src/eventlog.pp
@@ -23,9 +23,10 @@ uses SysUtils,Classes;
Type
TEventLog = Class;
- TLogType = (ltSystem,ltFile);
+ TLogType = (ltSystem,ltFile,ltStdOut,ltStdErr);
TLogCodeEvent = Procedure (Sender : TObject; Var Code : DWord) of Object;
TLogCategoryEvent = Procedure (Sender : TObject; Var Code : Word) of Object;
+ TLogMessageEvent = Procedure (Sender : TObject; EventType : TEventType; Const Msg : String) of Object;
TEventLog = Class(TComponent)
Private
@@ -44,6 +45,7 @@ Type
FOnGetCustomCategory : TLogCategoryEvent;
FOnGetCustomEventID : TLogCodeEvent;
FOnGetCustomEvent : TLogCodeEvent;
+ FOnLogMessage: TLogMessageEvent;
FPaused : Boolean;
procedure SetActive(const Value: Boolean);
procedure SetIdentification(const Value: String);
@@ -52,16 +54,20 @@ Type
procedure DeActivateLog;
procedure ActivateFileLog;
procedure SetFileName(const Value: String);
+ procedure ActivateIOLog;
procedure ActivateSystemLog;
function DefaultFileName: String;
+ function FormatLogMessage(EventType : TEventType; const Msg: String): String;
procedure WriteFileLog(EventType : TEventType; const Msg: String);
procedure WriteSystemLog(EventType: TEventType; const Msg: String);
+ procedure WriteIOLog(EventType: TEventType; const Msg: String; var OutFile: TextFile);
procedure DeActivateFileLog;
procedure DeActivateSystemLog;
procedure CheckIdentification;
Procedure DoGetCustomEventID(Var Code : DWord);
Procedure DoGetCustomEventCategory(Var Code : Word);
Procedure DoGetCustomEvent(Var Code : DWord);
+ Procedure DoLogMessage(EventType : TEventType; const Msg: String);
Protected
Procedure CheckInactive;
Procedure EnsureActive;
@@ -101,6 +107,7 @@ Type
Property OnGetCustomCategory : TLogCategoryEvent Read FOnGetCustomCategory Write FOnGetCustomCategory;
Property OnGetCustomEventID : TLogCodeEvent Read FOnGetCustomEventID Write FOnGetCustomEventID;
Property OnGetCustomEvent : TLogCodeEvent Read FOnGetCustomEvent Write FOnGetCustomEvent;
+ Property OnLogMessage : TLogMessageEvent read FOnLogMessage write FOnLogMessage;
Property Paused : Boolean Read FPaused Write FPaused;
End;
@@ -114,6 +121,8 @@ Resourcestring
SLogDebug = 'Debug';
SLogCustom = 'Custom (%d)';
SErrLogFailedMsg = 'Failed to log entry (Error: %s)';
+ SErrLogOpenStdOut = 'Standard Output not available for logging';
+ SErrLogOpenStdErr = 'Standard Error not available for logging';
implementation
@@ -201,20 +210,31 @@ begin
Case FlogType of
ltFile : WriteFileLog(EventType,Msg);
ltSystem : WriteSystemLog(EventType,Msg);
+ ltStdOut : WriteIOLog(EventType,Msg,StdOut);
+ ltStdErr : WriteIOLog(EventType,Msg,StdErr);
end;
+ DoLogMessage(EventType, Msg);
end;
-procedure TEventLog.WriteFileLog(EventType : TEventType; const Msg : String);
-
+function TEventLog.FormatLogMessage(EventType : TEventType; const Msg: String): String;
Var
- S,TS,T : String;
+ TS,T : String;
begin
If FTimeStampFormat='' then
FTimeStampFormat:='yyyy-mm-dd hh:nn:ss.zzz';
TS:=FormatDateTime(FTimeStampFormat,Now);
T:=EventTypeToString(EventType);
- S:=Format('%s [%s %s] %s%s',[Identification,TS,T,Msg,LineEnding]);
+ Result:=Format('%s [%s %s] %s',[Identification,TS,T,Msg]);
+end;
+
+procedure TEventLog.WriteFileLog(EventType : TEventType; const Msg : String);
+
+Var
+ S : String;
+
+begin
+ S:=FormatLogMessage(EventType, Msg)+LineEnding;
try
FStream.WriteBuffer(S[1],Length(S));
S:='';
@@ -226,6 +246,11 @@ begin
Raise ELogError.CreateFmt(SErrLogFailedMsg,[S]);
end;
+procedure TEventLog.WriteIOLog(EventType: TEventType; const Msg: String; var OutFile: TextFile);
+begin
+ Writeln(OutFile,FormatLogMessage(EventType,Msg));
+end;
+
procedure TEventLog.Log(const Fmt: String; Args: array of const);
begin
Log(Format(Fmt,Args));
@@ -249,6 +274,8 @@ begin
Case FLogType of
ltFile : ActivateFileLog;
ltSystem : ActivateSystemLog;
+ ltStdOut,
+ ltStdErr : ActivateIOLog;
end;
end;
@@ -258,6 +285,8 @@ begin
Case FLogType of
ltFile : DeActivateFileLog;
ltSystem : DeActivateSystemLog;
+ { nothing to do here }
+ ltStdOut,ltStdErr : ;
end;
end;
@@ -279,6 +308,24 @@ begin
FStream.Seek(0,soFromEnd);
end;
+Procedure TEventLog.ActivateIOLog;
+
+var
+ errmsg: String;
+ m: LongInt;
+
+begin
+ if FLogtype = ltStdOut then begin
+ m := TextRec(StdOut).Mode;
+ errmsg := SErrLogOpenStdOut;
+ end else begin
+ m := TextRec(StdErr).Mode;
+ errmsg := SErrLogOpenStdErr;
+ end;
+ if (m <> fmOutput) and (m <> fmAppend) then
+ raise ELogError.Create(errmsg);
+end;
+
Procedure TEventLog.DeActivateFileLog;
begin
@@ -354,6 +401,13 @@ begin
FOnGetCustomEvent(Self,Code);
end;
+Procedure TEventLog.DoLogMessage(EventType : TEventType; const Msg: String);
+
+begin
+ If Assigned(FOnLogMessage) then
+ FOnLogMessage(Self,EventType,Msg);
+end;
+
destructor TEventLog.Destroy;
begin
diff --git a/avx512-0037785/packages/fcl-db/src/sqldb/interbase/ibconnection.pp b/avx512-0037785/packages/fcl-db/src/sqldb/interbase/ibconnection.pp
index 35fa20d25a..d145066788 100644
--- a/avx512-0037785/packages/fcl-db/src/sqldb/interbase/ibconnection.pp
+++ b/avx512-0037785/packages/fcl-db/src/sqldb/interbase/ibconnection.pp
@@ -92,7 +92,8 @@ type
procedure GetFloat(CurrBuff, Buffer : pointer; Size : Byte);
procedure SetFloat(CurrBuff: pointer; Dbl: Double; Size: integer);
- procedure CheckError(ProcName : string; Status : PISC_STATUS);
+ procedure CheckError(ProcName : string; Status : PISC_STATUS;IgnoreErrors : Array of Longint); overload;
+ procedure CheckError(ProcName : string; Status : PISC_STATUS); overload;
procedure SetParameters(cursor : TSQLCursor; aTransation : TSQLTransaction; AParams : TParams);
procedure FreeSQLDABuffer(var aSQLDA : PXSQLDA);
function IsDialectStored: boolean;
@@ -170,6 +171,12 @@ const
INVALID_DATA = -1;
procedure TIBConnection.CheckError(ProcName : string; Status : PISC_STATUS);
+
+begin
+ CheckError(ProcName,Status,[]);
+end;
+
+procedure TIBConnection.CheckError(ProcName : string; Status : PISC_STATUS; IgnoreErrors : Array of Longint);
var
i,ErrorCode : longint;
Msg, SQLState : string;
@@ -181,6 +188,10 @@ begin
if ((Status[0] = 1) and (Status[1] <> 0)) then
begin
ErrorCode := Status[1];
+ if Length(IgnoreErrors)>0 then
+ for I in IgnoreErrors do
+ if I=ErrorCode then
+ Exit;
{$IFDEF LinkDynamically}
if assigned(fb_sqlstate) then // >= Firebird 2.5
begin
@@ -967,7 +978,8 @@ begin
if FSelectable and (CursorName<>'') then
begin
if isc_dsql_free_statement(@Status, @StatementHandle, DSQL_close)<>0 then
- CheckError('Close Cursor', Status); // Ignore this, it can already be closed.
+ // If transaction was closed (keepOpenOnCommit, then the cursor is already closed.
+ CheckError('Close Cursor', Status, [335544577]);
end;
end;
end;
diff --git a/avx512-0037785/packages/fcl-db/src/sqldb/mysql/mysqlconn.inc b/avx512-0037785/packages/fcl-db/src/sqldb/mysql/mysqlconn.inc
index fe5858050b..3aff95a893 100644
--- a/avx512-0037785/packages/fcl-db/src/sqldb/mysql/mysqlconn.inc
+++ b/avx512-0037785/packages/fcl-db/src/sqldb/mysql/mysqlconn.inc
@@ -1058,7 +1058,7 @@ begin
Result := 0
else
Result := EncodeDate(EY, EM, ED);
- Result := ComposeDateTime(Result, EncodeTime(EH, EN, ES, EMS));
+ Result := ComposeDateTime(Result, EncodeTimeInterval(EH, EN, ES, EMS));
end;
function TConnectionName.InternalStrToTime(C: pchar; Len: integer): TDateTime;
diff --git a/avx512-0037785/packages/fcl-db/src/sqldb/sqldb.pp b/avx512-0037785/packages/fcl-db/src/sqldb/sqldb.pp
index 88aca65cae..3118e0f545 100644
--- a/avx512-0037785/packages/fcl-db/src/sqldb/sqldb.pp
+++ b/avx512-0037785/packages/fcl-db/src/sqldb/sqldb.pp
@@ -802,6 +802,7 @@ type
Property Proxy : TSQLConnection Read FProxy;
Published
Property ConnectorType : String Read FConnectorType Write SetConnectorType;
+ Property Port;
end;
TSQLConnectionClass = Class of TSQLConnection;
@@ -1197,8 +1198,12 @@ end;
procedure TCustomSQLStatement.DeAllocateCursor;
begin
- if Assigned(FCursor) and Assigned(Database) then
- DataBase.DeAllocateCursorHandle(FCursor);
+ if Assigned(FCursor) then
+ begin
+ if Assigned(Database) then
+ DataBase.DeAllocateCursorHandle(FCursor);
+ FreeAndNil(FCursor);
+ end;
end;
function TCustomSQLStatement.ExpandMacros( OrigSQL : String ) : String;
@@ -1515,6 +1520,7 @@ begin
end;
finally;
DeAllocateCursorHandle(Cursor);
+ FreeAndNil(Cursor);
end;
end;
diff --git a/avx512-0037785/packages/fcl-net/src/netdb.pp b/avx512-0037785/packages/fcl-net/src/netdb.pp
index 583d3e899b..b945990e69 100644
--- a/avx512-0037785/packages/fcl-net/src/netdb.pp
+++ b/avx512-0037785/packages/fcl-net/src/netdb.pp
@@ -84,11 +84,37 @@ Const
MaxRecursion = 10;
MaxIP4Mapped = 10;
+ { from http://www.iana.org/assignments/dns-parameters }
+ DNSQRY_A = 1; // name to IP address
+ DNSQRY_AAAA = 28; // name to IP6 address
+ DNSQRY_A6 = 38; // name to IP6 (new)
+ DNSQRY_PTR = 12; // IP address to name
+ DNSQRY_MX = 15; // name to MX
+ DNSQRY_TXT = 16; // name to TXT
+ DNSQRY_CNAME = 5;
+ DNSQRY_SOA = 6;
+ DNSQRY_NS = 2;
+ DNSQRY_SRV = 33;
+
+ // Flags 1
+ QF_QR = $80;
+ QF_OPCODE = $78;
+ QF_AA = $04;
+ QF_TC = $02; // Truncated.
+ QF_RD = $01;
+
+ // Flags 2
+ QF_RA = $80;
+ QF_Z = $70;
+ QF_RCODE = $0F;
+
var
EtcPath: string;
{$endif FPC_USE_LIBC}
Type
+ TDNSRcode = (rcNoError, rcFormatError,rcServFail,rcNXDomain,
+ rcNotImpl,rcRefused,rcReserved,rcInvalid);
TDNSServerArray = Array of THostAddr;
TServiceEntry = record
Name : String;
@@ -134,6 +160,66 @@ Type
end;
{$ifndef FPC_USE_LIBC}
+
+Type
+ TPayLoad = Array[0..511] of Byte;
+ TPayLoadTCP = Array[0 .. 65535] of Byte;
+
+ TDNSHeader = packed Record
+ id : Array[0..1] of Byte;
+ flags1 : Byte;
+ flags2 : Byte;
+ qdcount : word;
+ ancount : word;
+ nscount : word;
+ arcount : word;
+ end;
+
+ TQueryData = packed Record
+ h: TDNSHeader;
+ Payload : TPayLoad;
+ end;
+
+ TQueryDataLength = packed record
+ length: Word;
+ hpl: TQueryData;
+ end;
+
+ TQueryDataLengthTCP = packed Record
+ length: Word;
+ h: TDNSHeader;
+ Payload : TPayLoadTCP;
+ end;
+
+ PRRData = ^TRRData;
+ TRRData = Packed record // RR record
+ Atype : Word; // Answer type
+ AClass : Word;
+ TTL : Cardinal;
+ RDLength : Word;
+ end;
+
+ TRRNameData = packed record
+ RRName : ShortString;
+ RRMeta : TRRData;
+ RDataSt : Word;
+ end;
+ TRRNameDataArray = array of TRRNameData;
+
+ TDNSDomainName = ShortString;
+ TDNSRR_SOA = packed record
+ mname, rname: TDNSDomainName;
+ serial,refresh,retry,expire,min: Cardinal;
+ end;
+ TDNSRR_MX = packed record
+ preference: Word;
+ exchange: TDNSDomainName;
+ end;
+ TDNSRR_SRV = packed record
+ priority, weight, port: Word;
+ target: TDNSDomainName;
+ end;
+
Var
DNSServers : TDNSServerArray;
DNSOptions : String;
@@ -189,6 +275,82 @@ Function GetProtocolByNumber(proto: Integer; Var H : TProtocolEntry) : boolean;
Function ProcessHosts(FileName : String) : PHostListEntry;
Function FreeHostsList(var List : PHostListEntry) : Integer;
Procedure HostsListToArray(var List : PHostListEntry; Var Hosts : THostEntryArray; FreeList : Boolean);
+
+Procedure CheckResolveFile;
+Function Query(Resolver : Integer; Var Qry,Ans : TQueryData; QryLen : Integer; Var AnsLen : Integer) : Boolean;
+function QueryTCP(Resolver : Integer; Var Qry: TQueryDataLength;
+ var Ans: TQueryDataLengthTCP; QryLen : Integer; Var AnsLen : Integer) : Boolean;
+Function BuildPayLoad(Var Q : TQueryData; Name : String; RR : Word; QClass : Word) : Integer;
+Function BuildPayLoadTCP(Var Q : TQueryDataLength; Name : String; RR : Word; QClass : Word) : Integer;
+
+Function SkipAnsQueries(Var Ans : TQueryData; L : Integer) : integer;
+Function SkipAnsQueries(Var Ans : TQueryDataLengthTCP; L : Integer) : integer;
+
+function stringfromlabel(pl: TPayLoad; var start: Integer): string;
+function stringfromlabel(pl: TPayLoadTCP; var start: Integer): string;
+Function CheckAnswer(Const Qry : TDNSHeader; Var Ans : TDNSHeader) : Boolean;
+function IsValidAtype(atype: Word): Boolean;
+
+function IsTruncated(R: TDNSHeader): Boolean;
+function GetRcode(R: TDNSHeader): TDNSRcode;
+function GetFixlenStr(pl: TPayLoad; startidx: Cardinal; len: Byte;
+ out res: ShortString): Byte;
+function GetFixlenStr(pl: TPayLoadTCP; startidx: Cardinal; len: Byte;
+ out res: ShortString): Byte;
+
+function NextNameRR(const pl: TPayLoadTCP; start: Word;
+ out RRName: TRRNameData): Boolean;
+function NextNameRR(const pl: TPayLoad; start: Word;
+ out RRName: TRRNameData): Boolean;
+
+function GetRRrecords(const pl: TPayloadTCP; var Start: Word; Count: Word):
+ TRRNameDataArray;
+function GetRRrecords(const pl: TPayload; var Start: Word; Count: Word):
+ TRRNameDataArray;
+
+function DnsLookup(dn: String; qtype: Word; out Ans: TQueryData;
+ out AnsLen: Longint): Boolean;
+function DnsLookup(dn: String; qtype: Word; out Ans: TQueryDataLengthTCP;
+ out AnsLen: Longint): Boolean;
+
+function DNSRRGetA(const RR: TRRNameData; const pl: TPayLoadTCP;
+ out IP: THostAddr): Boolean;
+function DNSRRGetA(const RR: TRRNameData; const pl: TPayLoad;
+ out IP: THostAddr): Boolean;
+function DNSRRGetCNAME(const RR: TRRNameData; const pl: TPayLoad;
+ out cn: TDNSDomainName): Boolean;
+function DNSRRGetCNAME(const RR: TRRNameData; const pl: TPayLoadTCP;
+ out cn: TDNSDomainName): Boolean;
+function DNSRRGetAAAA(const RR: TRRNameData; const pl: TPayLoadTCP;
+ out IP: THostAddr6): Boolean;
+function DNSRRGetAAAA(const RR: TRRNameData; const pl: TPayLoad;
+ out IP: THostAddr6): Boolean;
+function DNSRRGetNS(const RR: TRRNameData; const pl: TPayLoadTCP;
+ out NSName: TDNSDomainName): Boolean;
+function DNSRRGetNS(const RR: TRRNameData; const pl: TPayLoad;
+ out NSName: TDNSDomainName): Boolean;
+function DNSRRGetSOA(const RR: TRRNameData; const pl: TPayLoadTCP;
+ out dnssoa: TDNSRR_SOA): Boolean;
+function DNSRRGetSOA(const RR: TRRNameData; const pl: TPayLoad;
+ out dnssoa: TDNSRR_SOA): Boolean;
+function DNSRRGetText(const RR: TRRNameData; const pl: TPayLoad;
+ out dnstext: AnsiString): Boolean;
+function DNSRRGetText(const RR: TRRNameData; const pl: TPayLoadTCP;
+ out dnstext: AnsiString): Boolean;
+function DNSRRGetMX(const RR: TRRNameData; const pl: TPayLoadTCP;
+ out MX: TDNSRR_MX): Boolean;
+function DNSRRGetMX(const RR: TRRNameData; const pl: TPayLoad;
+ out MX: TDNSRR_MX): Boolean;
+function DNSRRGetPTR(const RR: TRRNameData; const pl: TPayLoadTCP;
+ out ptr: TDNSDomainName): Boolean;
+function DNSRRGetPTR(const RR: TRRNameData; const pl: TPayLoad;
+ out ptr: TDNSDomainName): Boolean;
+function DNSRRGetSRV(const RR: TRRNameData; const pl: TPayload;
+ out srv: TDNSRR_SRV): Boolean;
+function DNSRRGetSRV(const RR: TRRNameData; const pl: TPayloadTCP;
+ out srv: TDNSRR_SRV): Boolean;
+
+
{$endif FPC_USE_LIBC}
Implementation
@@ -201,54 +363,14 @@ uses
sysutils;
{$ifndef FPC_USE_LIBC}
+type
+ TTCPSocketResult = (srTimeout,srPartial,srSocketClose,srOK);
+
var
DefaultDomainListArr : array of string;
NDots: Integer;
-const
- { from http://www.iana.org/assignments/dns-parameters }
- DNSQRY_A = 1; // name to IP address
- DNSQRY_AAAA = 28; // name to IP6 address
- DNSQRY_A6 = 38; // name to IP6 (new)
- DNSQRY_PTR = 12; // IP address to name
- DNSQRY_MX = 15; // name to MX
- DNSQRY_TXT = 16; // name to TXT
- DNSQRY_CNAME = 5;
-
- // Flags 1
- QF_QR = $80;
- QF_OPCODE = $78;
- QF_AA = $04;
- QF_TC = $02; // Truncated.
- QF_RD = $01;
-
- // Flags 2
- QF_RA = $80;
- QF_Z = $70;
- QF_RCODE = $0F;
-
-
-Type
- TPayLoad = Array[0..511] of Byte;
- TQueryData = packed Record
- id : Array[0..1] of Byte;
- flags1 : Byte;
- flags2 : Byte;
- qdcount : word;
- ancount : word;
- nscount : word;
- arcount : word;
- Payload : TPayLoad;
- end;
-
- PRRData = ^TRRData;
- TRRData = Packed record // RR record
- Atype : Word; // Answer type
- AClass : Word;
- TTL : Cardinal;
- RDLength : Word;
- end;
{ ---------------------------------------------------------------------
Some Parsing routines
@@ -685,9 +807,10 @@ Var
begin
Result:=-1;
- If length(Name)>506 then
+ If (Length(Name) = 0) or (length(Name)>506) then
Exit;
- Result:=0;
+
+ Result:=0;
P:=@Q.Payload[0];
Repeat
L:=Pos('.',Name);
@@ -695,6 +818,17 @@ begin
S:=Length(Name)
else
S:=L-1;
+ // empty label is invalid, unless it's a dot at the end.
+ if (S = 0) then
+ begin
+ if (Length(Name) > 0) then
+ begin
+ Result := -1;
+ exit;
+ end
+ else
+ break; // empty label at end, break out for final 0 length byte.
+ end;
P[Result]:=S;
Move(Name[1],P[Result+1],S);
Inc(Result,S+1);
@@ -710,7 +844,23 @@ begin
Inc(Result,2);
end;
+{Construct a TCP query payload from the given name, rr and qclass. The
+ principal difference between the TCP and UDP payloads is the two-octet
+ length field in the TCP payload. The UDP payload has no length field.
+ See RFC-1035, section 4.2.2.
+
+ Returns the length of the constructed payload, which doesn't include
+ the header or the length field.}
+function BuildPayLoadTCP(var Q: TQueryDataLength; Name: String; RR: Word;
+ QClass: Word): Integer;
+var
+ l: Word;
+begin
+ l := BuildPayLoad(Q.hpl, Name, RR, QClass);
+ Q.length := htons(l + SizeOf(Q.hpl.h));
+ Result := l;
+end;
Function NextRR(Const PayLoad : TPayLoad;Var Start : LongInt; AnsLen : LongInt; Var RR : TRRData) : Boolean;
@@ -783,9 +933,8 @@ end;
{ ---------------------------------------------------------------------
QueryData handling functions
---------------------------------------------------------------------}
-
-Function CheckAnswer(Const Qry : TQueryData; Var Ans : TQueryData) : Boolean;
+function CheckAnswer(const Qry: TDNSHeader; var Ans: TDNSHeader): Boolean;
begin
Result:=False;
With Ans do
@@ -797,7 +946,7 @@ begin
If (Flags1 and QF_QR)=0 then
exit;
if (Flags1 and QF_OPCODE)<>0 then
- exit;
+ exit;
if (Flags2 and QF_RCODE)<>0 then
exit;
// Number of answers ?
@@ -808,6 +957,586 @@ begin
end;
end;
+{
+ Check that Atype is valid. These are the DNSQRY_? params we support. See the
+ definitions at the top of this unit for the names.
+ Deliberately excluding axfr (252), mailb (253), maila (254), and * (255).
+}
+function IsValidAtype(atype: Word): Boolean;
+begin
+ Result := False;
+ case atype of
+ 1 .. 16, 28, 33: Result := True;
+ end;
+end;
+
+function IsTruncated(R: TDNSHeader): Boolean;
+begin
+ Result := ((R.flags1 and QF_TC) > 0);
+end;
+
+function GetRcode(R: TDNSHeader): TDNSRcode;
+var
+ rcode_n: Byte;
+begin
+ rcode_n := (R.flags2 and QF_RCODE);
+ case rcode_n of
+ 0: Result := rcNoError;
+ 1: Result := rcFormatError;
+ 2: Result := rcServFail;
+ 3: Result := rcNXDomain;
+ 4: Result := rcNotImpl;
+ 5: Result := rcRefused;
+ 6 .. 15: Result := rcReserved;
+ else
+ Result := rcInvalid;
+ end;
+end;
+
+function GetFixlenStr(pl: TPayLoad; startidx: Cardinal; len: Byte; out
+ res: ShortString): Byte;
+begin
+ Result := 0;
+ res := '';
+ if (startidx + len) > Length(pl) then exit;
+ SetLength(res, len);
+ Move(pl[startidx], res[1], len);
+ Result := len;
+end;
+
+function GetFixlenStr(pl: TPayLoadTCP; startidx: Cardinal; len: Byte;
+ out res: ShortString): Byte;
+begin
+ Result := 0;
+ res := '';
+ if (startidx + len) > Length(pl) then exit;
+ SetLength(res, len);
+ Move(pl[startidx], res[1], len);
+ Result := len;
+end;
+
+function NextNameRR(const pl: TPayLoadTCP; start: Word; out RRName: TRRNameData
+ ): Boolean;
+var
+ I : Integer;
+ PA : PRRData;
+
+begin
+ Result:=False;
+ I:=Start;
+ if (Length(pl) - I) < (SizeOf(TRRData)+2) then exit;
+ RRName.RRName := stringfromlabel(pl, I);
+ if (Length(pl) - I) < (SizeOf(TRRData)) then exit;
+
+ PA:=PRRData(@pl[I]);
+ RRName.RRMeta := PA^;
+ RRName.RRMeta.AClass := NToHs(RRName.RRMeta.AClass);
+ RRName.RRMeta.Atype := NToHs(RRName.RRMeta.Atype);
+ if not IsValidAtype(RRName.RRMeta.Atype) then
+ exit;
+ RRName.RRMeta.RDLength := NToHs(RRName.RRMeta.RDLength);
+ RRName.RRMeta.TTL := NToHl(RRName.RRMeta.TTL);
+ RRName.RDataSt := I+SizeOf(TRRData);
+ // verify that start + rdlength is within the buffer boundary.
+ if RRName.RDataSt + RRName.RRMeta.RDLength > Length(pl) then exit;
+ Result := True;
+end;
+
+function NextNameRR(const pl: TPayLoad; start: Word; out RRName: TRRNameData
+ ): Boolean;
+var
+ I : Integer;
+ PA : PRRData;
+
+begin
+ Result:=False;
+ I:=Start;
+ if (Length(pl) - I) < (SizeOf(TRRData)+2) then exit;
+ RRName.RRName := stringfromlabel(pl, I);
+ if (Length(pl) - I) < (SizeOf(TRRData)) then exit;
+
+ PA:=PRRData(@pl[I]);
+ RRName.RRMeta := PA^;
+ RRName.RRMeta.AClass := NToHs(RRName.RRMeta.AClass);
+ RRName.RRMeta.Atype := NToHs(RRName.RRMeta.Atype);
+ if not IsValidAtype(RRName.RRMeta.Atype) then
+ exit;
+
+ RRName.RRMeta.RDLength := NToHs(RRName.RRMeta.RDLength);
+ RRName.RRMeta.TTL := NToHl(RRName.RRMeta.TTL);
+ RRName.RDataSt := I+SizeOf(TRRData);
+ // verify that start + rdlength is within the buffer boundary.
+ if RRName.RDataSt + RRName.RRMeta.RDLength > Length(pl) then exit;
+ Result := True;
+end;
+
+function GetRRrecords(const pl: TPayloadTCP; var Start: Word; Count: Word
+ ): TRRNameDataArray;
+var
+ I, Total: Word;
+ B: Boolean;
+ RRN: TRRNameData;
+
+begin
+ I:=0;
+ Total := 0;
+ SetLength(Result,Count);
+ while (I < Count) do
+ begin
+ B := NextNameRR(pl, Start, RRN);
+ if not B then break;
+ Inc(Total);
+ Result[I] := RRN;
+ Inc(I);
+ Start := RRN.RDataSt+RRN.RRMeta.RDLength;
+ end;
+ if Total < Count then SetLength(Result,Total);
+end;
+
+function GetRRrecords(const pl: TPayload; var Start: Word; Count: Word
+ ): TRRNameDataArray;
+var
+ I, Total: Word;
+ B: Boolean;
+ RRN: TRRNameData;
+
+begin
+ I:=0;
+ Total := 0;
+ SetLength(Result,Count);
+ while (I < Count) do
+ begin
+ B := NextNameRR(pl, Start, RRN);
+ if not B then break;
+ Inc(Total);
+ Result[I] := RRN;
+ Inc(I);
+ Start := RRN.RDataSt+RRN.RRMeta.RDLength;
+ end;
+ if Total < Count then SetLength(Result,Total);
+end;
+
+function DnsLookup(dn: String; qtype: Word; out Ans: TQueryData; out
+ AnsLen: Longint): Boolean;
+var
+ Qry: TQueryData;
+ QryLen: Longint;
+ idx: Word;
+begin
+ Result := False;
+ AnsLen := -2;
+
+ CheckResolveFile;
+ if Length(DNSServers) = 0 then
+ exit;
+
+ QryLen := BuildPayLoad(Qry, dn, qtype, 1);
+ if QryLen <= 0 then exit;
+
+ AnsLen := -1;
+ { Try the query at each configured resolver in turn, until one of them
+ returns an answer. We check for AnsLen > -1 because we need to distinguish
+ between failure to connect and the server saying it doesn't know or can't
+ answer. If AnsLen = -1 then we failed to connect. If AnsLen >= 0 but qr
+ = False, then we connected but the server returned an error code.}
+ idx := 0;
+ repeat
+ Result := Query(idx,Qry,Ans,QryLen,AnsLen);
+ Inc(idx);
+ until (idx > High(DNSServers)) or (Result = True) or (AnsLen >= 0);
+end;
+
+function DnsLookup(dn: String; qtype: Word; out Ans: TQueryDataLengthTCP; out
+ AnsLen: Longint): Boolean;
+var
+ Qry: TQueryDataLength;
+ QryLen: Longint;
+ idx: Word;
+
+begin
+ Result := False;
+ AnsLen := -2;
+
+ CheckResolveFile;
+ if Length(DNSServers) = 0 then
+ exit;
+
+ QryLen:=BuildPayLoadTCP(Qry, dn, qtype, 1);
+ if QryLen <= 0 then exit;
+ AnsLen := -1;
+
+ { Try the query at each configured resolver in turn, until one of them
+ returns an answer. We check for AnsLen > -1 because we need to distinguish
+ between failure to connect and the server saying it doesn't know or can't
+ answer. If AnsLen = -1 then we failed to connect. If AnsLen >= 0 but qr
+ = False, then we connected but the server returned an error code.}
+ idx := 0;
+ repeat
+ Result := QueryTCP(idx,Qry,Ans,QryLen,AnsLen);
+ Inc(idx);
+ until (idx > High(DNSServers)) or (Result = True) or (AnsLen >= 0);
+end;
+
+function DNSRRGetA(const RR: TRRNameData; const pl: TPayLoadTCP; out
+ IP: THostAddr): Boolean;
+begin
+ IP.s_addr := 0;
+ Result := False;
+ if RR.RRMeta.Atype <> DNSQRY_A then exit;
+ if (Length(pl) - RR.RDataSt) < 4 then exit;
+ Move(pl[RR.RDataSt], IP, SizeOf(THostAddr));
+ IP.s_addr := NToHl(IP.s_addr);
+ Result := True;
+end;
+
+function DNSRRGetA(const RR: TRRNameData; const pl: TPayLoad; out IP: THostAddr
+ ): Boolean;
+begin
+ IP.s_addr := 0;
+ Result := False;
+ if RR.RRMeta.Atype <> DNSQRY_A then exit;
+ if (Length(pl) - RR.RDataSt) < 4 then exit;
+ Move(pl[RR.RDataSt], IP, SizeOf(THostAddr));
+ IP.s_addr := NToHl(IP.s_addr);
+ Result := True;
+end;
+
+function DNSRRGetCNAME(const RR: TRRNameData; const pl: TPayLoad; out
+ cn: TDNSDomainName): Boolean;
+var
+ n: Integer;
+begin
+ Result := False;
+ cn := '';
+ if RR.RRMeta.Atype <> DNSQRY_CNAME then exit;
+ n := RR.RDataSt;
+ if (RR.RDataSt + RR.RRMeta.RDLength) > Length(pl) then exit;
+ cn := stringfromlabel(pl, n);
+ Result := True;
+end;
+
+function DNSRRGetCNAME(const RR: TRRNameData; const pl: TPayLoadTCP; out
+ cn: TDNSDomainName): Boolean;
+var
+ n: Integer;
+begin
+ Result := False;
+ cn := '';
+ if RR.RRMeta.Atype <> DNSQRY_CNAME then exit;
+ n := RR.RDataSt;
+ if (n + RR.RRMeta.rdlength) > Length(pl) then exit;
+ cn := stringfromlabel(pl, n);
+ Result := True;
+end;
+
+function DNSRRGetAAAA(const RR: TRRNameData; const pl: TPayLoadTCP; out
+ IP: THostAddr6): Boolean;
+begin
+ IP.s6_addr32[0] := 0;
+ IP.s6_addr32[1] := 0;
+ IP.s6_addr32[2] := 0;
+ IP.s6_addr32[3] := 0;
+ Result := False;
+ if RR.RRMeta.Atype <> DNSQRY_AAAA then exit;
+ if (RR.RDataSt + SizeOf(THostAddr6)) > Length(pl) then exit;
+ Move(pl[RR.RDataSt],IP,SizeOf(THostAddr6));
+ Result := True;
+end;
+
+function DNSRRGetAAAA(const RR: TRRNameData; const pl: TPayLoad; out
+ IP: THostAddr6): Boolean;
+begin
+ IP.s6_addr32[0] := 0;
+ IP.s6_addr32[1] := 0;
+ IP.s6_addr32[2] := 0;
+ IP.s6_addr32[3] := 0;
+ Result := False;
+ if RR.RRMeta.Atype <> DNSQRY_AAAA then exit;
+ if (RR.RDataSt + SizeOf(THostAddr6)) > Length(pl) then exit;
+ Move(pl[RR.RDataSt],IP,SizeOf(THostAddr6));
+ Result := True;
+end;
+
+function DNSRRGetNS(const RR: TRRNameData; const pl: TPayLoadTCP; out
+ NSName: TDNSDomainName): Boolean;
+var
+ n: LongInt;
+begin
+ NSName := '';
+ Result := False;
+ if RR.RRMeta.Atype <> DNSQRY_NS then exit;
+ if (RR.RDataSt + RR.RRMeta.RDLength) > Length(pl) then exit;
+ n := RR.RDataSt;
+ NSName := stringfromlabel(pl, n);
+ Result := True;
+end;
+
+function DNSRRGetNS(const RR: TRRNameData; const pl: TPayLoad; out
+ NSName: TDNSDomainName): Boolean;
+var
+ n: LongInt;
+begin
+ NSName := '';
+ Result := False;
+ if RR.RRMeta.Atype <> DNSQRY_NS then exit;
+ if (RR.RDataSt + RR.RRMeta.RDLength) > Length(pl) then exit;
+ n := RR.RDataSt;
+ NSName := stringfromlabel(pl, n);
+ Result := True;
+end;
+
+function DNSRRGetSOA(const RR: TRRNameData; const pl: TPayLoadTCP; out
+ dnssoa: TDNSRR_SOA): Boolean;
+var
+ idx: Integer;
+begin
+ // can't trust the counts we've been given, so check that we never
+ // exceed the end of the payload buffer.
+ idx := RR.RDataSt;
+ Result := False;
+ if RR.RRMeta.Atype <> DNSQRY_SOA then exit;
+ dnssoa.mname := stringfromlabel(pl, idx);
+ if idx >= Length(pl) then exit;
+
+ dnssoa.rname := stringfromlabel(pl, idx);
+
+ if (idx + (SizeOf(Cardinal) * 5)) > Length(pl) then exit;
+ Move(pl[idx],dnssoa.serial,SizeOf(Cardinal));
+ Inc(idx, SizeOf(Cardinal));
+ Move(pl[idx], dnssoa.refresh, SizeOf(Cardinal));
+ Inc(idx, SizeOf(Cardinal));
+ Move(pl[idx], dnssoa.retry, SizeOf(Cardinal));
+ Inc(idx, SizeOf(Cardinal));
+ Move(pl[idx], dnssoa.expire, SizeOf(Cardinal));
+ Inc(idx, SizeOf(Cardinal));
+ Move(pl[idx], dnssoa.min, SizeOf(Cardinal));
+ Result := True;
+ dnssoa.serial := NToHl(dnssoa.serial);
+ dnssoa.min := NToHl(dnssoa.min);
+ dnssoa.expire := NToHl(dnssoa.expire);
+ dnssoa.refresh := NToHl(dnssoa.refresh);
+ dnssoa.retry := NToHl(dnssoa.retry);
+end;
+
+function DNSRRGetSOA(const RR: TRRNameData; const pl: TPayLoad; out
+ dnssoa: TDNSRR_SOA): Boolean;
+var
+ idx: Integer;
+begin
+ // can't trust the counts we've been given, so check that we never
+ // exceed the end of the payload buffer.
+ idx := RR.RDataSt;
+ Result := False;
+ if RR.RRMeta.Atype <> DNSQRY_SOA then exit;
+ dnssoa.mname := stringfromlabel(pl, idx);
+ if idx >= Length(pl) then exit;
+
+ dnssoa.rname := stringfromlabel(pl, idx);
+
+ if (idx + (SizeOf(Cardinal) * 5)) > Length(pl) then exit;
+ Move(pl[idx],dnssoa.serial,SizeOf(Cardinal));
+ Inc(idx, SizeOf(Cardinal));
+ Move(pl[idx], dnssoa.refresh, SizeOf(Cardinal));
+ Inc(idx, SizeOf(Cardinal));
+ Move(pl[idx], dnssoa.retry, SizeOf(Cardinal));
+ Inc(idx, SizeOf(Cardinal));
+ Move(pl[idx], dnssoa.expire, SizeOf(Cardinal));
+ Inc(idx, SizeOf(Cardinal));
+ Move(pl[idx], dnssoa.min, SizeOf(Cardinal));
+ Result := True;
+ dnssoa.serial := NToHl(dnssoa.serial);
+ dnssoa.min := NToHl(dnssoa.min);
+ dnssoa.expire := NToHl(dnssoa.expire);
+ dnssoa.refresh := NToHl(dnssoa.refresh);
+ dnssoa.retry := NToHl(dnssoa.retry);
+end;
+
+function DNSRRGetText(const RR: TRRNameData; const pl: TPayLoad; out
+ dnstext: AnsiString): Boolean;
+var
+ wrk: ShortString;
+ idx: LongInt;
+ l: Byte;
+begin
+ Result := False;
+ dnstext := '';
+ if RR.RRMeta.Atype <> DNSQRY_TXT then exit;
+ wrk := '';
+
+ idx := RR.RDataSt;
+ if (Length(pl) - idx) < 2 then exit;
+
+ repeat
+ l := GetFixlenStr(pl, idx+1, pl[idx], wrk);
+ if l = 0 then exit; // count would send us past end of buffer
+ dnstext := dnstext + wrk;
+ Inc(idx, l+1);
+ until (idx >= (RR.RDataSt + RR.RRMeta.RDLength)) or ((Length(pl) - idx) < 2);
+ Result := True;
+end;
+
+function DNSRRGetText(const RR: TRRNameData; const pl: TPayLoadTCP; out
+ dnstext: AnsiString): Boolean;
+var
+ wrk: ShortString;
+ idx: LongInt;
+ l: Byte;
+begin
+ Result := False;
+ dnstext := '';
+ if RR.RRMeta.Atype <> DNSQRY_TXT then exit;
+ wrk := '';
+
+ idx := RR.RDataSt;
+ if (Length(pl) - idx) < 2 then exit;
+
+ repeat
+ l := GetFixlenStr(pl, idx+1, pl[idx], wrk);
+ if l = 0 then exit; // count would send us past end of buffer
+ dnstext := dnstext + wrk;
+ Inc(idx, l+1);
+ until (idx >= (RR.RDataSt + RR.RRMeta.RDLength)) or ((Length(pl) - idx) < 2);
+ Result := True;
+end;
+
+function DNSRRGetMX(const RR: TRRNameData; const pl: TPayLoadTCP; out
+ MX: TDNSRR_MX): Boolean;
+var
+ idx: Integer;
+begin
+ Result := False;
+ MX.preference := 0;
+ MX.exchange := '';
+ if RR.RRMeta.Atype <> DNSQRY_MX then exit;
+ idx := RR.RDataSt;
+ if idx + SizeOf(Word) >= Length(pl) then exit;
+ Move(pl[idx],MX.preference, SizeOf(Word));
+ Inc(idx, SizeOf(Word));
+ if (Length(pl) - idx) < 2 then exit;
+ MX.exchange := stringfromlabel(pl, idx);
+ MX.preference := NToHs(MX.preference);
+ Result := True;
+end;
+
+function DNSRRGetMX(const RR: TRRNameData; const pl: TPayLoad; out MX: TDNSRR_MX
+ ): Boolean;
+var
+ idx: Integer;
+begin
+ Result := False;
+ MX.preference := 0;
+ MX.exchange := '';
+ if RR.RRMeta.Atype <> DNSQRY_MX then exit;
+ idx := RR.RDataSt;
+ if idx + SizeOf(Word) >= Length(pl) then exit;
+ Move(pl[idx],MX.preference, SizeOf(Word));
+ Inc(idx, SizeOf(Word));
+ if (Length(pl) - idx) < 2 then exit;
+ MX.exchange := stringfromlabel(pl, idx);
+ MX.preference := NToHs(MX.preference);
+ Result := True;
+end;
+
+function DNSRRGetPTR(const RR: TRRNameData; const pl: TPayLoadTCP; out
+ ptr: TDNSDomainName): Boolean;
+var
+ n: Integer;
+begin
+ Result := False;
+ ptr := '';
+ if RR.RRMeta.Atype <> DNSQRY_PTR then exit;
+ n := RR.RDataSt;
+ if (n + RR.RRMeta.RDLength) > Length(pl) then exit;
+ ptr := stringfromlabel(pl, n);
+ Result := True;
+end;
+
+function DNSRRGetPTR(const RR: TRRNameData; const pl: TPayLoad; out
+ ptr: TDNSDomainName): Boolean;
+var
+ n: Integer;
+begin
+ Result := False;
+ ptr := '';
+ if RR.RRMeta.Atype <> DNSQRY_PTR then exit;
+ n := RR.RDataSt;
+ if (n + RR.RRMeta.RDLength) > Length(pl) then exit;
+ ptr := stringfromlabel(pl, n);
+ Result := True;
+end;
+
+function DNSRRGetSRV(const RR: TRRNameData; const pl: TPayload; out
+ srv: TDNSRR_SRV): Boolean;
+var
+ idx: Integer;
+begin
+ Result := False;
+ srv.priority := 0;
+ srv.weight := 0;
+ srv.port := 0;
+ srv.target := '';
+ if RR.RRMeta.Atype <> DNSQRY_SRV then exit;
+
+ idx := RR.RDataSt;
+ if idx + RR.RRMeta.RDLength > Length(pl) then exit;
+
+ Move(pl[idx], srv.priority, SizeOf(Word));
+ Inc(idx, SizeOf(Word));
+ if (Length(pl) - idx) < 2 then exit;
+
+ Move(pl[idx], srv.weight, SizeOf(Word));
+ Inc(idx, SizeOf(Word));
+ if (Length(pl) - idx) < 2 then exit;
+
+ Move(pl[idx], srv.port, SizeOf(Word));
+ Inc(idx, SizeOf(Word));
+ if (Length(pl) - idx) < 2 then exit;
+
+ srv.target := stringfromlabel(pl, idx);
+
+ srv.priority := NToHs(srv.priority);
+ srv.weight := NToHs(srv.weight);
+ srv.port := NToHs(srv.port);
+
+ Result := True;
+end;
+
+function DNSRRGetSRV(const RR: TRRNameData; const pl: TPayloadTCP; out
+ srv: TDNSRR_SRV): Boolean;
+var
+ idx: Integer;
+begin
+ Result := False;
+ srv.priority := 0;
+ srv.weight := 0;
+ srv.port := 0;
+ srv.target := '';
+ if RR.RRMeta.Atype <> DNSQRY_SRV then exit;
+
+ idx := RR.RDataSt;
+ if idx + RR.RRMeta.RDLength > Length(pl) then exit;
+
+ Move(pl[idx], srv.priority, SizeOf(Word));
+ Inc(idx, SizeOf(Word));
+ if (Length(pl) - idx) < 2 then exit;
+
+ Move(pl[idx], srv.weight, SizeOf(Word));
+ Inc(idx, SizeOf(Word));
+ if (Length(pl) - idx) < 2 then exit;
+
+ Move(pl[idx], srv.port, SizeOf(Word));
+ Inc(idx, SizeOf(Word));
+ if (Length(pl) - idx) < 2 then exit;
+
+ srv.target := stringfromlabel(pl, idx);
+
+ srv.priority := NToHs(srv.priority);
+ srv.weight := NToHs(srv.weight);
+ srv.port := NToHs(srv.port);
+
+ Result := True;
+end;
+
Function SkipAnsQueries(Var Ans : TQueryData; L : Integer) : integer;
Var
@@ -817,10 +1546,10 @@ begin
Result:=0;
With Ans do
begin
- qdcount := htons(qdcount);
+ h.qdcount := htons(h.qdcount);
i:=0;
q:=0;
- While (Q<qdcount) and (i<l) do
+ While (Q<h.qdcount) and (i<l) do
begin
If Payload[i]>63 then
begin
@@ -842,6 +1571,39 @@ begin
end;
end;
+function SkipAnsQueries(var Ans: TQueryDataLengthTCP; L: Integer): integer;
+var
+ Q,I : Integer;
+
+begin
+ Result:=0;
+ With Ans do
+ begin
+ h.qdcount := htons(h.qdcount);
+ i:=0;
+ q:=0;
+ While (Q<h.qdcount) and (i<l) do
+ begin
+ If Payload[i]>63 then
+ begin
+ Inc(I,6);
+ Inc(Q);
+ end
+ else
+ begin
+ If Payload[i]=0 then
+ begin
+ inc(q);
+ Inc(I,5);
+ end
+ else
+ Inc(I,Payload[i]+1);
+ end;
+ end;
+ Result:=I;
+ end;
+end;
+
{ ---------------------------------------------------------------------
DNS Query functions.
---------------------------------------------------------------------}
@@ -857,7 +1619,7 @@ Var
begin
Result:=False;
- With Qry do
+ With Qry.h do
begin
ID[0]:=Random(256);
ID[1]:=Random(256);
@@ -890,39 +1652,256 @@ begin
AL:=SizeOf(SA);
L:=fprecvfrom(Sock,@ans,SizeOf(Ans),0,@SA,@AL);
fpclose(Sock);
- // Check lenght answer and fields in header data.
- If (L<12) or not CheckAnswer(Qry,Ans) Then
+
+ if L < 12 then exit;
+ // Return Payload length.
+ Anslen:=L-12;
+ // even though we may still return false to indicate an error, if AnsLen
+ // is >= 0 then the caller knows the dns server responded.
+ If not CheckAnswer(Qry.h,Ans.h) Then
exit;
- // Return Payload length.
- Anslen:=L-12;
- Result:=True;
+ Result:=True;
+ //end;
end;
-function stringfromlabel(pl: TPayLoad; start: integer): string;
+function FetchDNSResponse(sock: Cint; out len: ssize_t;
+ out Ans: TQueryDataLengthTCP): TTCPSocketResult;
var
- l,i: integer;
+ respsize: Word;
+ L: ssize_t;
+
+begin
+ Result := srOK;
+ len := 0;
+
+ // peek into the socket buffer and see if a full message is waiting.
+ L := fprecv(sock, @Ans, SizeOf(Ans), MSG_PEEK);
+ if L = 0 then
+ begin
+ Result := srSocketClose;
+ exit;
+ end;
+ // The first two bytes of a DNS TCP payload is the number of octets in the
+ // response, excluding the two bytes of length. This lets us see if we've
+ // received the full response.
+ respsize := NToHs(Ans.length);
+ if (L < 2) or (L < (respsize + SizeOf(Ans.length))) then
+ begin
+ Result := srPartial;
+ exit;
+ end;
+
+ // The full DNS response is waiting in the buffer. Get it now.
+ len := fprecv(sock, @Ans, SizeOf(Ans), 0);
+end;
+
+function QueryTCP(Resolver: Integer; var Qry: TQueryDataLength;
+ var Ans: TQueryDataLengthTCP; QryLen: Integer; var AnsLen: Integer): Boolean;
+Var
+ SA : TInetSockAddr;
+ Sock : cint;
+ L: ssize_t;
+ RTO : Longint;
+ ReadFDS : TFDSet;
+ count: Integer;
+ sendsize: ssize_t;
+ respsize: Word;
+ resp: TTCPSocketResult;
+ tstart: QWord;
+
+begin
+ tstart := GetTickCount64;
+ Result:=False;
+ With Qry.hpl.h do
+ begin
+ ID[0]:=Random(256);
+ ID[1]:=Random(256);
+ Flags1:=QF_RD;
+ Flags2:=0;
+ qdcount:=htons(1); // was 1 shl 8;
+ ancount:=0;
+ nscount:=0;
+ arcount:=0;
+ end;
+ Sock:=FpSocket(AF_INET,SOCK_STREAM,0);
+ If Sock=-1 then
+ exit;
+ With SA do
+ begin
+ sin_family:=AF_INET;
+ sin_port:=htons(DNSport);
+ sin_addr.s_addr:=cardinal(DNSServers[Resolver]); // octets already in net order
+ end;
+
+ // connect to the resolver
+ if (fpconnect(Sock, @SA, SizeOf(SA)) <> 0) then
+ exit;
+
+ // send the query to the resolver
+ sendsize := QryLen + SizeOf(Qry.hpl.h) + SizeOf(Qry.length);
+ count := fpsend(Sock,@Qry,sendsize,0);
+ if count < sendsize then
+ begin
+ fpclose(Sock);
+ exit;
+ end;
+
+ // tell other side we're done writing.
+ fpshutdown(Sock, SHUT_WR);
+
+ RTO := 5000;
+ fpFD_ZERO(ReadFDS);
+ fpFD_Set(sock,ReadFDS);
+
+ // select to wait for data
+ if fpSelect(sock+1, @ReadFDS, Nil, Nil, RTO)<=0 then
+ begin
+ // timed out, nothing received.
+ fpclose(sock);
+ exit;
+ end;
+
+ // for partial responses, keep trying until all data received or the
+ // timeout period has elapsed. the timeout period includes the time
+ // spent waiting on select.
+ resp := FetchDNSResponse(Sock, L, Ans);
+ while (resp = srPartial) and ((GetTickCount64 - tstart) < RTO) do
+ begin
+ // need to sleep to avoid high cpu. 50ms means a 5 second timeout will
+ // make up to 100 calls to FetchDNSResponse.
+ Sleep(50);
+ resp := FetchDNSResponse(Sock, L, Ans);
+ end;
+
+ fpclose(sock);
+ if resp <> srOK then exit;
+
+ // Set AnsLen to be the size of the payload minus the header.
+ Anslen := L-SizeOf(Qry.hpl.h);
+ // if the final check finds problems with the answer, we'll return false
+ // but AnsLen being >=0 will let the caller know that the server did
+ // respond, but either declined to answer or couldn't.
+ If not CheckAnswer(Qry.hpl.h,Ans.h) then
+ exit;
+ Result:=True;
+end;
+
+{
+Read a string from the payload buffer. Handles compressed as well as
+regular labels. On termination start points to the character after the
+end of the str.
+}
+
+function stringfromlabel(pl: TPayLoad; var start: Integer): string;
+var
+ l,i,n,lc: integer;
+ ptr: Word;
+ ptrseen: Boolean = False;
begin
result := '';
l := 0;
i := 0;
+ n := start;
+ // Label counter. Per rfc1035, s. 3.1, each label is at least 2 bytes and the
+ // max length for a domain is 255, so there can't be more than 127 labels.
+ // This helps to short-circuit loops in label pointers.
+ lc := 0;
repeat
- l := ord(pl[start]);
+ // each iteration of this loop is for one label. whether a pointer or a
+ // regular label, we need 2 bytes headroom minimum.
+ if n > (Length(pl) - 2) then break;
+ l := ord(pl[n]);
{ compressed reply }
while (l >= 192) do
begin
- { the -12 is because of the reply header length }
- start := (l and not(192)) shl 8 + ord(pl[start+1]) - 12;
- l := ord(pl[start]);
+ if not ptrseen then start := n + 2;
+ ptrseen := True;
+ ptr := (l and not(192)) shl 8 + ord(pl[n+1]);
+ {ptr must point backward and be >= 12 (for the dns header.}
+ if (ptr >= (n+12)) or (ptr < 12) then l := 0 // l=0 causes loop to exit
+ else
+ begin
+ { the -12 is because of the reply header length. we do the decrement
+ here to avoid overflowing if ptr < 12.}
+ n := ptr - 12;
+ l := ord(pl[n]);
+ end;
+ end;
+ // check we point inside the buffer
+ if (n+l+1) > Length(pl) then l := 0;
+ if l <> 0 then begin
+ setlength(result,length(result)+l);
+ move(pl[n+1],result[i+1],l);
+ result := result + '.';
+ inc(n,l); inc(n);
+ inc(i,l); inc(i);
+ if n > start then start := n;
+ end;
+ Inc(lc); // label count
+ until (l = 0) or (lc > 127);
+ // per rfc1035, section 4.1.4, a domain name may be represented by
+ // either a sequence of labels followed by 0, or a pointer, or a series
+ // of labels followed by a pointer. If there's a pointer there's no 0 to
+ // skip over when calculating the final index.
+ if not ptrseen then Inc(start); // jump past the 0.
+ if (Length(result) > 0) and (result[length(result)] = '.') then
+ setlength(result,length(result)-1);
+end;
+
+function stringfromlabel(pl: TPayLoadTCP; var start: Integer): string;
+var
+ l,i,n,lc: integer;
+ ptr: Word;
+ ptrseen: Boolean = False;
+begin
+ result := '';
+ l := 0;
+ i := 0;
+ n := start;
+ // Label counter. Per rfc1035, s. 3.1, each label is at least 2 bytes and the
+ // max length for a domain is 255, so there can't be more than 127 labels.
+ // This helps to short-circuit loops in label pointers.
+ lc := 0;
+ repeat
+ // each iteration of this loop is for one label. whether a pointer or a
+ // regular label, we need 2 bytes headroom minimum.
+ if n > (Length(pl) - 2) then break;
+ l := ord(pl[n]);
+ { compressed reply }
+ while (l >= 192) do
+ begin
+ if not ptrseen then start := n + 2;
+ ptrseen := True;
+ ptr := (l and not(192)) shl 8 + ord(pl[n+1]);
+ {ptr must point backward and be >= 12 (for the dns header.}
+ if (ptr >= (n+12)) or (ptr < 12) then l := 0 // l=0 causes loop to exit
+ else
+ begin
+ { the -12 is because of the reply header length. we do the decrement
+ here to avoid overflowing if ptr < 12.}
+ n := ptr - 12;
+ l := ord(pl[n]);
+ end;
end;
+ // check we point inside the buffer
+ if (n+l+1) > Length(pl) then l := 0;
if l <> 0 then begin
setlength(result,length(result)+l);
- move(pl[start+1],result[i+1],l);
+ move(pl[n+1],result[i+1],l);
result := result + '.';
- inc(start,l); inc(start);
+ inc(n,l); inc(n);
inc(i,l); inc(i);
+ if n > start then start := n;
end;
- until l = 0;
- if result[length(result)] = '.' then setlength(result,length(result)-1);
+ Inc(lc); // label count
+ until (l = 0) or (lc > 127);
+ // per rfc1035, section 4.1.4, a domain name may be represented by
+ // either a sequence of labels followed by 0, or a pointer, or a series
+ // of labels followed by a pointer. If there's a pointer there's no 0 to
+ // skip over when calculating the final index.
+ if not ptrseen then Inc(start); // jump past the 0.
+ if (Length(result) > 0) and (result[length(result)] = '.') then
+ setlength(result,length(result)-1);
end;
Function ResolveNameAt(Resolver : Integer; HostName : String; Var Addresses : Array of THostAddr; Recurse: Integer) : Integer;
@@ -941,7 +1920,7 @@ begin
else
begin
AnsStart:=SkipAnsQueries(Ans,AnsLen);
- MaxAnswer:=Ans.AnCount-1;
+ MaxAnswer:=Ans.h.AnCount-1;
If MaxAnswer>High(Addresses) then
MaxAnswer:=High(Addresses);
I:=0;
@@ -1022,7 +2001,7 @@ begin
end else
begin
AnsStart:=SkipAnsQueries(Ans,AnsLen);
- MaxAnswer:=Ans.AnCount-1;
+ MaxAnswer:=Ans.h.AnCount-1;
If MaxAnswer>High(Addresses) then
MaxAnswer:=High(Addresses);
I:=0;
@@ -1085,7 +2064,7 @@ begin
else
begin
AnsStart:=SkipAnsQueries(Ans,AnsLen);
- MaxAnswer:=Ans.AnCount-1;
+ MaxAnswer:=Ans.h.AnCount-1;
If MaxAnswer>High(Names) then
MaxAnswer:=High(Names);
I:=0;
diff --git a/avx512-0037785/packages/fcl-net/tests/netdbtest.pp b/avx512-0037785/packages/fcl-net/tests/netdbtest.pp
new file mode 100644
index 0000000000..4a70bc76fa
--- /dev/null
+++ b/avx512-0037785/packages/fcl-net/tests/netdbtest.pp
@@ -0,0 +1,4615 @@
+unit netdbtest;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, fpcunit, testregistry, Sockets, math, netdb;
+
+const
+ FAKETLD = 'doesnotexist';
+ FAKEDOMAIN = 'fakedomain';
+
+ FAKEFQDN=FAKEDOMAIN+'.'+FAKETLD;
+
+type
+ TDomainCompressionOffset = packed record
+ nm: String;
+ offset: Word;
+ end;
+ TDomainCompressionTable = Array of TDomainCompressionOffset;
+
+ TTwoByteArr = array[0 .. 1] of Byte;
+ TDNSDomainPointer = packed record
+ case b: boolean of
+ true: (ba: TTwoByteArr);
+ false: (b1,b2: Byte);
+ end;
+
+ TDNSDomainByteStream = packed record
+ ulabels: Array of byte;
+ cptr: Word;
+ end;
+
+ TBuffer = Array of Byte;
+
+ // can't use dynamic arrays in variant records, so fudge things by
+ // having between 1 and 5 subsstrings per text RR. it's good enough
+ // for these tests.
+ TTextArray = array [1 .. 5] of ShortString;
+
+ TFakeQuery = record
+ nm: ShortString;
+ qtype, qclass: Word;
+ end;
+
+ TFakeSOA = record
+ mn,rn: ShortString;
+ serial,refresh,retry,expire,min: Cardinal;
+ end;
+ TFakeMX = record
+ pref: Word;
+ exch: ShortString;
+ end;
+ TFakeSRV = record
+ priority, weight, port: Word;
+ target: ShortString;
+ end;
+
+ TFakeRR = record
+ RRName : ShortString;
+ AClass : Word;
+ TTL : Cardinal;
+ RDLength : Word;
+ case Atype: Word of
+ DNSQRY_A: (ip: THostAddr);
+ DNSQRY_AAAA: (ip6: THostAddr6);
+ DNSQRY_CNAME: (cn: ShortString);
+ DNSQRY_MX: (fmx: TFakeMX);
+ DNSQRY_NS: (nsh: ShortString);
+ DNSQRY_PTR: (ptr: ShortString);
+ DNSQRY_SOA: (fsoa: TFakeSoa);
+ DNSQRY_TXT: (sstrcount: Byte; txtarr: TTextArray);
+ DNSQRY_SRV: (fsrv: TFakeSRV);
+ end;
+
+ TRRSection = Array of TFakeRR;
+
+ TFakeDNSResponse = record
+ strtable: TDomainCompressionTable;
+ compresslabels: Boolean;
+ hdr: TDNSHeader;
+ qry: TFakeQuery;
+ answers, authority, additional: TRRSection;
+ end;
+
+ TRDataWriteRes = packed record
+ bw, etw: Word;
+ end;
+
+ { TNetDbTest }
+
+ TNetDbTest= class(TTestCase)
+ strict private
+ tsl: TStringList;
+ protected
+ procedure SetUp; override;
+ procedure TearDown; override;
+
+ procedure BuildFakeRR_A(out RR: TFakeRR; nm: String; ttl: Cardinal;
+ val: String);
+ procedure BuildFakeRR_AAAA(out RR: TFakeRR; nm: String; ttl: Cardinal;
+ val: String);
+ procedure BuildFakeRR_MX(out RR: TFakeRR; nm: String; ttl: Cardinal;
+ pref: Word; exch: ShortString );
+ procedure BuildFakeRR_NS(out RR: TFakeRR; nm: String; ttl: Cardinal;
+ val: String);
+ procedure BuildFakeRR_PTR(out RR: TFakeRR; nm: String; ttl: Cardinal;
+ val: String);
+ procedure BuildFakeRR_CNAME(out RR: TFakeRR; nm: String; ttl: Cardinal;
+ val: String);
+ procedure BuildFakeRR_SOA(out RR: TFakeRR; nm: String; ttl: Cardinal;
+ mn,rn: ShortString; serial,refresh,retry,expire,min: Cardinal);
+ procedure BuildFakeRR_TXT(out RR: TFakeRR; nm: String; ttl: Cardinal;
+ n: Byte; txt: TTextArray);
+ procedure BuildFakeRR_SRV(out RR: TFakeRR; nm: String; ttl: Cardinal;
+ priority, weight, port: Word; target: ShortString);
+
+ procedure CopyBytesTo(var buf: TPayLoad; startidx,destidx,count: Word);
+ procedure CopyBytesTo(var buf: TPayLoadTCP; startidx,destidx,count: Word);
+
+ function WriteNumToBuffer(var buf: TBuffer; var offset: Cardinal;
+ val: Word): Word;
+ function WriteNumToBuffer(var buf: TBuffer; var offset: Cardinal;
+ val: Cardinal): Word;
+
+ function WriteNumToBufferN(var buf: TBuffer; var offset: Cardinal;
+ val: Word): Word;
+ function WriteNumToBufferN(var buf: TBuffer; var offset: Cardinal;
+ val: Cardinal): Word;
+
+ function WriteMXAsRData(var buf: TBuffer; var offset: Cardinal;
+ fmx: TFakeMX): TRDataWriteRes;
+ function WriteSOAasRData(var buf: TBuffer; var offset: Cardinal;
+ fsoa: TFakeSOA): TRDataWriteRes;
+ function WriteSOAasRData(var buf: TBuffer; var offset: Cardinal;
+ fsoa: TFakeSOA; var ctbl: TDomainCompressionTable): TRDataWriteRes;
+ function WriteAAAAasRData(var buf: TBuffer; var offset: Cardinal;
+ ip6: THostAddr6): TRDataWriteRes;
+ function WriteAasRData(var buf: TBuffer; var offset: Cardinal;
+ ip: THostAddr): TRDataWriteRes;
+
+ function WriteSRVasRData(var buf: TBuffer; var offset: Cardinal;
+ fsrv: TFakeSRV): TRDataWriteRes;
+ function WriteSRVasRData(var buf: TBuffer; var offset: Cardinal;
+ fsrv: TFakeSRV; var ctbl: TDomainCompressionTable): TRDataWriteRes;
+
+ function WriteMXAsRData(var buf: TBuffer; var offset: Cardinal;
+ fmx: TFakeMX; var ctbl: TDomainCompressionTable): TRDataWriteRes;
+
+ function CalcRdLength(o: TDNSDomainByteStream): Word;
+ function CalcRdLength(o: TTextArray): Word;
+ function WriteTextRecAsRData(var buf: TBuffer; var offset: Cardinal;
+ tt: TTextArray): TRDataWriteRes;
+
+ function DomainNameToByteStream(nm: ShortString;
+ var ctbl: TDomainCompressionTable): TDNSDomainByteStream;
+ function DomainNameToByteStream(nm: ShortString): TDNSDomainByteStream;
+
+ function WriteDNSDomainByteStreamToBuffer(var buf: TBuffer;
+ var offset: Cardinal; dbs: TDNSDomainByteStream): Word;
+
+ function WriteDomainAsRdata(var buf: TBuffer; var offset: Cardinal;
+ dbs: TDNSDomainByteStream): TRDataWriteRes;
+
+ function WriteRRToBuffer(var buf: TBuffer; var offset: Cardinal;
+ rr: TFakeRR): Word;
+ function WriteRRToBuffer(var buf: TBuffer; var offset: Cardinal;
+ rr: TFakeRR; var ctbl: TDomainCompressionTable): Word;
+ function FakeDNSResponseToByteBuffer(fdr: TFakeDNSResponse;
+ out buf: TBuffer; compress: Boolean = False): Cardinal;
+ function BufferToPayload(const buf: TBuffer; out pl: TPayload): Boolean;
+ function BufferToPayload(const buf: TBuffer; out pl: TPayLoadTCP): Boolean;
+
+ function BuildQueryData(fdr: TFakeDNSResponse; out qd: TQueryData;
+ out qlen: Word; Compress: Boolean = False): Boolean;
+
+ function BuildQueryData(fdr: TFakeDNSResponse;
+ out qd: TQueryDataLengthTCP; out qlen: Word;
+ Compress: Boolean = False): Boolean;
+
+ function BuildTruncatedQueryData(fdr: TFakeDNSResponse; out qd: TQueryData;
+ out qlen: Word; truncoffset: Word): Boolean;
+
+ procedure BuildFakeResponseA(nm: ShortString; out fr: TFakeDNSResponse);
+ procedure BuildFakeResponseAAAA(nm: ShortString; out fr: TFakeDNSResponse);
+ procedure BuildFakeResponseMX(nm: ShortString; out fr: TFakeDNSResponse);
+ procedure BuildFakeResponseSOA(nm: ShortString; out fr: TFakeDNSResponse);
+ procedure BuildFakeResponseCNAME(nm: ShortString; out fr: TFakeDNSResponse);
+ procedure BuildFakeResponseNS(nm: ShortString; out fr: TFakeDNSResponse);
+ procedure BuildFakeResponsePTR(nm: ShortString; out fr: TFakeDNSResponse);
+ procedure BuildFakeResponseTXT(nm: ShortString; out fr: TFakeDNSResponse);
+ procedure BuildFakeResponseSRV(nm: ShortString; out fr: TFakeDNSResponse);
+
+ published
+ procedure TestBuildPayloadSimple;
+ procedure TestBuildPayloadSimpleEmpty;
+ procedure TestBuildPayloadSimpleEndDot;
+ procedure TestBuildPayloadSimpleStartDot;
+ procedure TestBuildPayloadSimpleMultipleDot;
+
+ { * straightforward tests for the api with valid data. Have to test each
+ * known RR type with both TCP and UDP buffer functions, and with and
+ * without compression of domain names.
+ * No network calls will be made. These tests hit all functions for
+ * processing dns requests except network functions.}
+ procedure TestDnsQueryUDP_A;
+ procedure TestDnsQueryTCP_A;
+ procedure TestDnsQueryCompressUDP_A;
+ procedure TestDnsQueryCompressTCP_A;
+
+ procedure TestDnsQueryUDP_AAAA;
+ procedure TestDnsQueryTCP_AAAA;
+ procedure TestDnsQueryCompressUDP_AAAA;
+ procedure TestDnsQueryCompressTCP_AAAA;
+
+ procedure TestDnsQueryUDP_MX;
+ procedure TestDnsQueryTCP_MX;
+ procedure TestDnsQueryCompressUDP_MX;
+ procedure TestDnsQueryCompressTCP_MX;
+
+ procedure TestDnsQueryUDP_SOA;
+ procedure TestDnsQueryTCP_SOA;
+ procedure TestDnsQueryCompressUDP_SOA;
+ procedure TestDnsQueryCompressTCP_SOA;
+
+ procedure TestDnsQueryUDP_CNAME;
+ procedure TestDnsQueryTCP_CNAME;
+ procedure TestDnsQueryCompressUDP_CNAME;
+ procedure TestDnsQueryCompressTCP_CNAME;
+
+ procedure TestDnsQueryUDP_NS;
+ procedure TestDnsQueryTCP_NS;
+ procedure TestDnsQueryCompressUDP_NS;
+ procedure TestDnsQueryCompressTCP_NS;
+
+ procedure TestDnsQueryUDP_PTR;
+ procedure TestDnsQueryTCP_PTR;
+ procedure TestDnsQueryCompressUDP_PTR;
+ procedure TestDnsQueryCompressTCP_PTR;
+
+ procedure TestDnsQueryUDP_TXT;
+ procedure TestDnsQueryTCP_TXT;
+ procedure TestDnsQueryCompressUDP_TXT;
+ procedure TestDnsQueryCompressTCP_TXT;
+
+ procedure TestDnsQueryUDP_SRV;
+ procedure TestDnsQueryTCP_SRV;
+ procedure TestDnsQueryCompressUDP_SRV;
+ procedure TestDnsQueryCompressTCP_SRV;
+
+ {
+ * Tests with invalid input data. These attempt to simulate a hostile
+ * dns server returning deliberately invalid data in an attempt to
+ * cause a buffer overflow, memory corruption, or DDOS.
+ }
+
+ // buffer truncated so RRs have invalid types.
+ procedure TestDnsQueryTruncateRR_UDP_A;
+
+ {
+ * Tests of DNSRRGet* functions where RR is near the end of the buffer,
+ * testing both when the RR just fits, and when it doesn't.
+ }
+ procedure TestDnsRRBufferEdgeA;
+ procedure TestDnsRRBufferPastEdgeA;
+ procedure TestDnsRRBufferEdgeAAAA;
+ procedure TestDNsRRBufferPastEdgeAAAA;
+ procedure TestDnsRRBufferEdgeMX;
+ procedure TestDnsRRBufferPastEdgeMX;
+ procedure TestDnsRRBufferEdgeSOA;
+ procedure TestDnsRRBufferPastEdgeSOA;
+ procedure TestDnsRRBufferEdgeSRV;
+ procedure TestDnsRRBufferPastEdgeSRV;
+ procedure TestDnsRRBufferEdgeCNAME;
+ procedure TestDnsRRBufferPastEdgeCNAME;
+ procedure TestDnsRRBufferEdgeNS;
+ procedure TestDnsRRBufferPastEdgeNS;
+ procedure TestDnsRRBufferEdgePTR;
+ procedure TestDnsRRBufferPastEdgePTR;
+ procedure TestDnsRRBufferEdgeTXT;
+ procedure TestDnsRRBufferPastEdgeTXT;
+
+
+ {
+ * the TCP variants. identical code, but qd variable is a different type
+ * and so different paths get followed in netdb.
+ }
+ procedure TestDnsRRBufferEdgeTCPA;
+ procedure TestDnsRRBufferPastEdgeTCPA;
+ procedure TestDnsRRBufferEdgeTCPAAAA;
+ procedure TestDNsRRBufferPastEdgeTCPAAAA;
+ procedure TestDnsRRBufferEdgeTCPMX;
+ procedure TestDnsRRBufferPastEdgeTCPMX;
+ procedure TestDnsRRBufferEdgeTCPSOA;
+ procedure TestDnsRRBufferPastEdgeTCPSOA;
+ procedure TestDnsRRBufferEdgeTCPSRV;
+ procedure TestDnsRRBufferPastEdgeTCPSRV;
+ procedure TestDnsRRBufferEdgeTCPCNAME;
+ procedure TestDnsRRBufferPastEdgeTCPCNAME;
+ procedure TestDnsRRBufferEdgeTCPNS;
+ procedure TestDnsRRBufferPastEdgeTCPNS;
+ procedure TestDnsRRBufferEdgeTCPPTR;
+ procedure TestDnsRRBufferPastEdgeTCPPTR;
+ procedure TestDnsRRBufferEdgeTCPTXT;
+ procedure TestDnsRRBufferPastEdgeTCPTXT;
+
+ // Testing of NextNameRR at buffer edge and beyond. this differs from
+ // the above tests in that they tests DNSGet* at the edge, but NextNameRR
+ // is never called to read at the edge in those functions.
+ // Because NextNameRR does nothing that is specific to RR types it's
+ // not necessary to test with each type of RR.
+
+ procedure TestNextNameRREdgeA;
+ procedure TestNextNameRRPastEdgeA;
+ procedure TestNextNameRREdgeTCPA;
+ procedure TestNextNameRRPastEdgeTCPA;
+
+ {
+ * Test GetRRrecords at and beyond buffer boundaries.
+ }
+ procedure TestGetRRrecordsInvalidStart;
+ procedure TestGetRRrecordsInvalidStartTCP;
+
+ {
+ Tests for GetFixlenStr
+ }
+ procedure TestGetFixLenStrSimple;
+ procedure TestGetFixLenStrSimpleTCP;
+ procedure TestGetFixLenStrSimpleAtEdge;
+ procedure TestGetFixLenStrSimpleTCPAtEdge;
+ procedure TestGetFixLenStrSimplePastEdge;
+ procedure TestGetFixLenStrSimpleTCPPastEdge;
+
+
+ {
+ * Test stringfromlabel with buffer edges and beyond. Its behaviour
+ * at present is to drop any label that would exceed the buffer boundary
+ * but still return any other labels successfully received.
+
+ * Some of the previous tests already verify what happens with a label
+ * that occurs on the edge. See the tests for TestDnsRRBufferEdgeSRV
+ * and TestDnsRRBufferEdgeTCPSRV, TestDnsRRBufferEdgeCNAME, etc.
+ }
+
+ // read a label starting at the end of the buffer where the count is
+ // greater than 0.
+ procedure TestStringFromLabelCountAsLastByte;
+ procedure TestStringFromLabelCountAsLastByteTCP;
+
+ // compressed label
+ procedure TestStringFromLabelCompress;
+ procedure TestStringFromLabelCompressTCP;
+ // another compressed label test, this time with one uncompressed label
+ procedure TestStringFromLabelCompressWithUncompressedLabel;
+ // as above, but on the tcp payload buffer
+ procedure TestStringFromLabelCompressWithUncompressedLabelTCP;
+ // compressed label at the edge of the buffer
+ procedure TestStringFromLabelCompressEndBuffer;
+ // compressed label at the edge of the tcp buffer
+ procedure TestStringFromLabelCompressEndBufferTCP;
+ // test stringfromlabel when last byte is 192. 192 is the signal
+ // that the next byte is a pointer offset, but of course there's
+ // no next byte.
+ procedure TestStringFromLabelCompressSplit;
+ // repeat using TCP buffer variant
+ procedure TestStringFromLabelCompressSplitTCP;
+ // test that stringfromlabel rejects pointers that go forward. per
+ // rfc 1035, pointers must go backward.
+ procedure TestStringFromLabelCompressPtrFwd;
+ procedure TestStringFromLabelCompressPtrFwdTCP;
+ // fill buffer with 192, pointer marker, then try stringfromlabel on it.
+ procedure TestStringFromLabelCompressAllPtrStart;
+ procedure TestStringFromLabelCompressAllPtrStartTCP;
+
+ // test string from label where second byte is 0.
+ procedure TestStringFromLabelCompressedZero;
+ procedure TestStringFromLabelCompressedZeroTCP;
+
+ // test whether an infinite loop can be triggered.
+ procedure TestStringFromLabelInfiniteLoop;
+ procedure TestStringFromLabelInfiniteLoopTCP;
+
+ // test short domain less than 12 chars. this tests that dns pointer
+ // calculations in stringfromlabel are correct
+ procedure TestCompressShortDomain;
+ procedure TestCompressShortDomainTCP;
+ end;
+
+implementation
+
+procedure dump_payload(const pl: TBuffer);
+var
+ idx,llen: Cardinal;
+begin
+ idx := 0;
+ llen := 0;
+ for idx := 0 to Length(pl) - 1 do
+ begin
+ write('['+inttostr(idx)+'] '+IntToHex(pl[idx],2));
+ if (pl[idx] > 48) and (pl[idx] < 123) then
+ write(' ' + chr(pl[idx]))
+ else
+ write(' .');
+ write(' ');
+ Inc(llen);
+ if llen >= 6 then
+ begin
+ llen := 0;
+ writeln();
+ end;
+ end;
+ if llen > 0 then
+ begin
+ writeln();
+ end;
+end;
+
+procedure dump_payload(const pl: TPayload; count: Word);
+var
+ idx,llen: Cardinal;
+begin
+ idx := 0;
+ llen := 0;
+ for idx := 0 to count - 1 do
+ begin
+ write('['+inttostr(idx)+'] '+IntToHex(pl[idx],2));
+ if (pl[idx] > 48) and (pl[idx] < 123) then
+ write(' ' + chr(pl[idx]))
+ else
+ write(' .');
+ write(' ');
+ Inc(llen);
+ if llen >= 6 then
+ begin
+ llen := 0;
+ writeln();
+ end;
+ end;
+ if llen > 0 then
+ begin
+ writeln();
+ end;
+end;
+
+function LookupStr(ls: String; stt: TDomainCompressionTable; out idx: Word): Boolean;
+var
+ so: TDomainCompressionOffset;
+begin
+ Result := False;
+ for so in stt do
+ begin
+ if ls = so.nm then
+ begin
+ Result := True;
+ idx := so.offset;
+ exit;
+ end;
+ end;
+end;
+
+function AddStr(ls: String; var stt: TDomainCompressionTable; idx: Word): Boolean;
+var
+ so: TDomainCompressionOffset;
+begin
+ so.nm := ls;
+ so.offset := idx;
+ SetLength(stt, Length(stt)+1);
+ stt[Length(stt)-1] := so;
+ Result := True;
+end;
+
+function GetDnsDomainPointer(offset: Word): TDNSDomainPointer;
+begin
+ Result.b1 := 0;
+ Result.b2 := 0;
+ // dns comp. ptr can't be > 2 ** 14 or 16383
+ if offset > 16383 then exit;
+ Result.b1 := (offset SHR 8) OR 192;
+ Result.b2 := (offset AND $00FF);
+end;
+
+procedure DomainNameToLabels(const dmn: String; var labels: TStringList);
+begin
+ labels.Clear;
+ labels.Delimiter := '.';
+ labels.StrictDelimiter := True;
+ labels.DelimitedText := dmn;
+end;
+
+procedure TNetDbTest.BuildFakeRR_A(out RR: TFakeRR; nm: String; ttl: Cardinal;
+ val: String);
+begin
+ RR.RRName := nm;
+ RR.Atype := DNSQRY_A;
+ RR.AClass := 1;
+ RR.TTL := ttl;
+ RR.ip := StrToNetAddr(val);
+ RR.RDLength := 4;
+end;
+
+procedure TNetDbTest.BuildFakeRR_AAAA(out RR: TFakeRR; nm: String;
+ ttl: Cardinal; val: String);
+begin
+ RR.RRName := nm;
+ RR.Atype := DNSQRY_AAAA;
+ RR.AClass := 1;
+ RR.TTL := ttl;
+ RR.ip6 := StrToNetAddr6(val);
+ RR.RDLength := 16;
+end;
+
+procedure TNetDbTest.BuildFakeRR_MX(out RR: TFakeRR; nm: String; ttl: Cardinal;
+ pref: Word; exch: ShortString );
+begin
+ RR.RRName := nm;
+ RR.Atype := DNSQRY_MX;
+ RR.AClass := 1;
+ RR.TTL := ttl;
+ RR.fmx.pref := pref;
+ RR.fmx.exch := exch;
+end;
+
+procedure TNetDbTest.BuildFakeRR_NS(out RR: TFakeRR; nm: String; ttl: Cardinal;
+ val: String);
+begin
+ RR.RRName := nm;
+ RR.Atype := DNSQRY_NS;
+ RR.AClass := 1;
+ RR.TTL := ttl;
+ RR.nsh := val;
+end;
+
+procedure TNetDbTest.BuildFakeRR_PTR(out RR: TFakeRR; nm: String; ttl: Cardinal;
+ val: String);
+begin
+ RR.RRName := nm;
+ RR.Atype := DNSQRY_PTR;
+ RR.AClass := 1;
+ RR.TTL := ttl;
+ RR.ptr := val;
+end;
+
+procedure TNetDbTest.BuildFakeRR_CNAME(out RR: TFakeRR; nm: String;
+ ttl: Cardinal; val: String);
+begin
+ RR.RRName := nm;
+ RR.Atype := DNSQRY_CNAME;
+ RR.AClass := 1;
+ RR.TTL := ttl;
+ RR.cn := val;
+end;
+
+procedure TNetDbTest.BuildFakeRR_SOA(out RR: TFakeRR; nm: String; ttl: Cardinal;
+ mn,rn: ShortString; serial,refresh,retry,expire,min: Cardinal);
+begin
+ RR.RRName := nm;
+ RR.Atype := DNSQRY_SOA;
+ RR.AClass := 1;
+ RR.TTL := ttl;
+ RR.fsoa.mn := mn;
+ RR.fsoa.rn := rn;
+ RR.fsoa.serial := serial;
+ RR.fsoa.refresh := refresh;
+ RR.fsoa.retry := retry;
+ RR.fsoa.expire := expire;
+ RR.fsoa.min := min;
+end;
+
+procedure TNetDbTest.BuildFakeRR_TXT(out RR: TFakeRR; nm: String; ttl: Cardinal;
+ n: Byte; txt: TTextArray);
+var
+ idx: Byte;
+begin
+ RR.RRName := nm;
+ RR.Atype := DNSQRY_TXT;
+ RR.AClass := 1;
+ RR.TTL := ttl;
+ RR.sstrcount := n;
+ RR.txtarr[1] := '';
+ RR.txtarr[2] := '';
+ RR.txtarr[3] := '';
+ RR.txtarr[4] := '';
+ RR.txtarr[5] := '';
+ for idx := Low(txt) to Min(n, High(txt)) do
+ RR.txtarr[idx] := txt[idx];
+end;
+
+procedure TNetDbTest.BuildFakeRR_SRV(out RR: TFakeRR; nm: String; ttl: Cardinal;
+ priority, weight, port: Word; target: ShortString);
+begin
+ RR.RRName := nm;
+ RR.Atype := DNSQRY_SRV;
+ RR.AClass := 1;
+ RR.TTL := ttl;
+ RR.fsrv.priority := priority;
+ RR.fsrv.weight := weight;
+ RR.fsrv.port := port;
+ RR.fsrv.target := target;
+end;
+
+function TNetDbTest.CalcRdLength(o: TTextArray): Word;
+var
+ tmps: ShortString;
+begin
+ Result := 0;
+ for tmps in o do
+ begin
+ if tmps = '' then break;
+ Result := Result + Length(tmps)+1; // don't forget length byte!
+ end;
+end;
+
+function TNetDbTest.WriteAasRData(var buf: TBuffer; var offset: Cardinal;
+ ip: THostAddr): TRDataWriteRes;
+var
+ s,l: Word;
+begin
+ s := offset;
+ l := SizeOf(ip.s_addr);
+ Result.etw := l + 2; //rdlength +2 for length itself
+ // rdlength
+ WriteNumToBuffer(buf, offset, l);
+ // rr data
+ WriteNumToBufferN(buf, offset, ip.s_addr);
+ Result.bw := offset - s;
+end;
+
+function TNetDbTest.WriteSRVasRData(var buf: TBuffer; var offset: Cardinal;
+ fsrv: TFakeSRV): TRDataWriteRes;
+var
+ s, l: Word;
+ dmbs: TDNSDomainByteStream;
+begin
+ s := offset;
+ dmbs := DomainNameToByteStream(fsrv.target);
+ l := CalcRdLength(dmbs) + SizeOf(Word) * 3;
+ Result.etw := l + 2; //rdlength +2 for length byte
+
+ // rdlength
+ WriteNumToBuffer(buf, offset, l);
+
+ // RR data
+ WriteNumToBuffer(buf, offset, fsrv.priority);
+ WriteNumToBuffer(buf, offset, fsrv.weight);
+ WriteNumToBuffer(buf, offset, fsrv.port);
+ WriteDNSDomainByteStreamToBuffer(buf, offset, dmbs);
+ Result.bw := offset - s;
+end;
+
+function TNetDbTest.WriteSRVasRData(var buf: TBuffer; var offset: Cardinal;
+ fsrv: TFakeSRV; var ctbl: TDomainCompressionTable): TRDataWriteRes;
+var
+ s, l: Word;
+ dmbs: TDNSDomainByteStream;
+begin
+ s := offset;
+ dmbs := DomainNameToByteStream(fsrv.target, ctbl);
+ l := CalcRdLength(dmbs) + SizeOf(Word) * 3;
+ Result.etw := l + 2; //rdlength +2 for length byte
+
+ // rdlength
+ WriteNumToBuffer(buf, offset, l);
+
+ // RR data
+ WriteNumToBuffer(buf, offset, fsrv.priority);
+ WriteNumToBuffer(buf, offset, fsrv.weight);
+ WriteNumToBuffer(buf, offset, fsrv.port);
+ WriteDNSDomainByteStreamToBuffer(buf, offset, dmbs);
+ Result.bw := offset - s;
+end;
+
+function TNetDbTest.WriteMXAsRData(var buf: TBuffer; var offset: Cardinal;
+ fmx: TFakeMX; var ctbl: TDomainCompressionTable): TRDataWriteRes;
+var
+ s, l: Word;
+ dmbs: TDNSDomainByteStream;
+begin
+ s := offset;
+ dmbs := DomainNameToByteStream(fmx.exch, ctbl);
+ l := SizeOf(fmx.pref) + CalcRdLength(dmbs);
+ Result.etw := l + 2; // we'll write rdlength bytes+2 bytes for length itself.
+
+ // rdlength
+ WriteNumToBuffer(buf, offset, l);
+
+ // RR data
+ // pref
+ WriteNumToBuffer(buf, offset, fmx.pref);
+ // exchange
+ WriteDNSDomainByteStreamToBuffer(buf, offset, dmbs);
+ Result.bw := offset - s;
+end;
+
+function TNetDbTest.CalcRdLength(o: TDNSDomainByteStream): Word;
+begin
+ Result := Length(o.ulabels);
+ if o.cptr > 0 then Inc(Result,2);
+end;
+
+function TNetDbTest.WriteAAAAasRData(var buf: TBuffer; var offset: Cardinal;
+ ip6: THostAddr6): TRDataWriteRes;
+var
+ s,l: Word;
+begin
+ s := offset;
+ l := SizeOf(ip6.u6_addr32);
+ Result.etw := l + 2; //rdlength + 2 for length itself
+ // rdlength
+ WriteNumToBuffer(buf, offset, l);
+ // rr data
+ Move(ip6.s6_addr, buf[offset], l);
+ Inc(offset, l);
+ Result.bw := offset - s;
+end;
+
+function TNetDbTest.WriteSOAasRData(var buf: TBuffer; var offset: Cardinal;
+ fsoa: TFakeSOA): TRDataWriteRes;
+var
+ s, l: Word;
+ dmbsmn, dmbsrn: TDNSDomainByteStream;
+begin
+ s := offset;
+ dmbsmn := DomainNameToByteStream(fsoa.mn);
+ dmbsrn := DomainNameToByteStream(fsoa.rn);
+ l := CalcRdLength(dmbsmn) + CalcRdLength(dmbsrn) + (SizeOf(Cardinal) * 5);
+
+ Result.etw := l + 2; // rdlength bytes + 2 for length itself
+
+ // rdlength
+ WriteNumToBuffer(buf, offset, l);
+
+ // rr data
+ WriteDNSDomainByteStreamToBuffer(buf, offset, dmbsmn);
+ WriteDNSDomainByteStreamToBuffer(buf, offset, dmbsrn);
+
+ WriteNumToBuffer(buf, offset, fsoa.serial);
+ WriteNumToBuffer(buf, offset, fsoa.refresh);
+ WriteNumToBuffer(buf, offset, fsoa.retry);
+ WriteNumToBuffer(buf, offset, fsoa.expire);
+ WriteNumToBuffer(buf, offset, fsoa.min);
+
+ Result.bw := offset - s;
+end;
+
+function TNetDbTest.WriteSOAasRData(var buf: TBuffer; var offset: Cardinal;
+ fsoa: TFakeSOA; var ctbl: TDomainCompressionTable): TRDataWriteRes;
+var
+ s, l: Word;
+ dmbsmn, dmbsrn: TDNSDomainByteStream;
+begin
+ s := offset;
+ dmbsmn := DomainNameToByteStream(fsoa.mn, ctbl);
+ dmbsrn := DomainNameToByteStream(fsoa.rn, ctbl);
+ l := CalcRdLength(dmbsmn) + CalcRdLength(dmbsrn) + (SizeOf(Cardinal) * 5);
+ Result.etw := l + 2; // rdlength bytes + 2 for length itself
+
+ // rdlength
+ WriteNumToBuffer(buf, offset, l);
+
+ // rr data
+ WriteDNSDomainByteStreamToBuffer(buf, offset, dmbsmn);
+ WriteDNSDomainByteStreamToBuffer(buf, offset, dmbsrn);
+
+ WriteNumToBuffer(buf, offset, fsoa.serial);
+ WriteNumToBuffer(buf, offset, fsoa.refresh);
+ WriteNumToBuffer(buf, offset, fsoa.retry);
+ WriteNumToBuffer(buf, offset, fsoa.expire);
+ WriteNumToBuffer(buf, offset, fsoa.min);
+
+ Result.bw := offset - s;
+end;
+
+function TNetDbTest.WriteMXAsRData(var buf: TBuffer; var offset: Cardinal;
+ fmx: TFakeMX): TRDataWriteRes;
+var
+ s, l: Word;
+ dmbs: TDNSDomainByteStream;
+begin
+ Result.bw := 0;
+ s := offset;
+ dmbs := DomainNameToByteStream(fmx.exch);
+ l := SizeOf(fmx.pref) + CalcRdLength(dmbs);
+ Result.etw := l + 2; // we'll write rdlength + 2 bytes for the length itself.
+
+ // rdlength
+ WriteNumToBuffer(buf, offset, l);
+
+ // RR data
+ // pref
+ WriteNumToBuffer(buf, offset, fmx.pref);
+ // exchange
+ dmbs := DomainNameToByteStream(fmx.exch);
+ WriteDNSDomainByteStreamToBuffer(buf, offset, dmbs);
+ Result.bw := offset - s;
+end;
+
+function TNetDbTest.WriteTextRecAsRData(var buf: TBuffer; var offset: Cardinal;
+ tt: TTextArray): TRDataWriteRes;
+var
+ s, l: Word;
+ ws: ShortString;
+begin
+ s := offset;
+ l := CalcRdLength(tt);
+ Result.etw := l + 2; // rdlength +2 for length itself
+ // rdlength
+ WriteNumToBuffer(buf, offset, l);
+
+ for ws in tt do
+ begin
+ if ws = '' then break;
+ Move(ws, buf[offset], Length(ws)+1);
+ Inc(offset,Length(ws)+1);
+ end;
+
+ Result.bw := offset - s;
+end;
+
+{
+Convert a domain name into a byte stream. Compression is supported using the
+supplied compression table.
+}
+function TNetDbTest.DomainNameToByteStream(nm: ShortString;
+ var ctbl: TDomainCompressionTable): TDNSDomainByteStream;
+var
+ dmn: ShortString;
+ offset,cmpoffset: Word;
+ ptrseen: Boolean = False;
+begin
+ SetLength(Result.ulabels, 0);
+ Result.cptr := 0;
+ offset := 0;
+
+ if nm = '' then exit;
+ DomainNameToLabels(nm, tsl);
+ if tsl.Count = 0 then exit;
+
+ dmn := '';
+ cmpoffset := 0;
+
+ {
+ for a domain a.b.c, using the lookup table,
+ -> lookup (a.b.c), if not found, add to table,
+ -> lookup (b.c), if not found, add to table,
+ -> lookup (c), if not found, add to table,
+
+ buf if any label domain is found, add the pointer to the buffer and stop.
+ }
+ repeat
+ dmn := tsl.DelimitedText;
+ ptrseen := LookupStr(dmn, ctbl, cmpoffset);
+ if ptrseen then
+ begin
+ // found the domain name. add a pointer, then we're done. Per RFC1035,
+ // section 4.1.4, a domain name is either a series of labels, a pointer,
+ // or a series of labels ending with a pointer. There's just one pointer
+ // for a domain name.
+ Result.cptr := cmpoffset;
+ break;
+ end
+ else
+ begin
+ // add the last full domain we looked up, not the working label,
+ // to the compression lookup table. E.g, add a.b.c rather than a.
+ // Add 12 for the dns header, which our buffer doesn't include, but
+ // api methods like stringfromlabel adjust offsets to account for it.
+ if Length(dmn) > 0 then AddStr(dmn, ctbl, offset+12);
+ // write the label to the buffer
+ dmn := tsl[0];
+ tsl.Delete(0);
+ SetLength(Result.ulabels, (Length(Result.ulabels) + Length(dmn)+1));
+ Result.ulabels[offset] := Length(dmn);
+ Inc(offset);
+ Move(dmn[1], Result.ulabels[offset], Length(dmn));
+ Inc(offset, Length(dmn));
+ end;
+ until tsl.Count = 0;
+
+ // if we didn't see a pointer then we have to write a 0. see rfc1035, s4.1.4.
+ if not ptrseen then
+ begin
+ SetLength(Result.ulabels, Length(Result.ulabels) + 1);
+ Result.ulabels[offset] := 0;
+ Inc(offset);
+ end;
+end;
+
+{
+This version of DomainNameToByteStream doesn't compress.
+}
+function TNetDbTest.DomainNameToByteStream(nm: ShortString
+ ): TDNSDomainByteStream;
+var
+ dmn: ShortString;
+ offset: Word;
+begin
+ SetLength(Result.ulabels, 0);
+ Result.cptr := 0;
+ offset := 0;
+
+ if nm = '' then exit;
+ DomainNameToLabels(nm, tsl);
+ if tsl.Count = 0 then exit;
+
+ for dmn in tsl do
+ begin
+ SetLength(Result.ulabels, (Length(Result.ulabels) + Length(dmn)+1));
+ Result.ulabels[offset] := Length(dmn);
+ Inc(offset);
+ Move(dmn[1], Result.ulabels[offset], Length(dmn));
+ Inc(offset, Length(dmn));
+ end;
+
+ SetLength(Result.ulabels, Length(Result.ulabels) + 1);
+ Result.ulabels[offset] := 0;
+end;
+
+function TNetDbTest.WriteDNSDomainByteStreamToBuffer(var buf: TBuffer;
+ var offset: Cardinal; dbs: TDNSDomainByteStream): Word;
+var
+ p: TDNSDomainPointer;
+ so: Word;
+begin
+ Result := 0;
+ // no label, no pointer, no write for you.
+ if (Length(dbs.ulabels) = 0) and (dbs.cptr = 0) then exit;
+ if (offset + CalcRdLength(dbs)) > Length(buf) then exit;
+
+ so := offset;
+ // labels can be empty, in which case we're writing just a pointer.
+ if Length(dbs.ulabels) > 0 then
+ begin
+ Move(dbs.ulabels[0], buf[offset], Length(dbs.ulabels));
+ Inc(offset, Length(dbs.ulabels));
+ end;
+ if dbs.cptr > 0 then
+ begin
+ p := GetDnsDomainPointer(dbs.cptr);
+ Move(p.ba, buf[offset], Length(p.ba));
+ Inc(offset, Min(Length(p.ba), (Length(buf) - offset)));
+ end;
+ Result := offset - so;
+end;
+
+{
+Write a domain name as RDATA. This means an RDLength (Word) and the
+domain labels.
+}
+function TNetDbTest.WriteDomainAsRdata(var buf: TBuffer; var offset: Cardinal;
+ dbs: TDNSDomainByteStream): TRDataWriteRes;
+var
+ s,l: Word;
+begin
+ l := CalcRdLength(dbs);
+ Result.etw := l + 2;
+ s := offset;
+ WriteNumToBuffer(buf, offset,l);
+ WriteDNSDomainByteStreamToBuffer(buf, offset, dbs);
+ Result.bw := offset - s;
+end;
+
+
+procedure TNetDbTest.BuildFakeResponseA(nm: ShortString; out
+ fr: TFakeDNSResponse);
+begin
+ // metadata
+ SetLength(fr.strtable, 0);
+
+ // start by building a fake header.
+ fr.hdr.ID[0] := 12;
+ fr.hdr.ID[1] := 34;
+ fr.hdr.flags1 := QF_QR or QF_RD;
+ fr.hdr.flags2 := 0;
+ fr.hdr.qdcount := 1;
+ fr.hdr.ancount := 2;
+ fr.hdr.nscount := 0;
+ fr.hdr.arcount := 0;
+
+ // Next is the query part
+ fr.qry.nm := nm;
+ fr.qry.qclass := 1;
+ fr.qry.qtype := DNSQRY_A;
+
+ // now the answer RRs
+ SetLength(fr.answers,2);
+ BuildFakeRR_A(fr.answers[0], nm, 300, '127.0.0.1');
+ BuildFakeRR_A(fr.answers[1], nm, 215, '127.0.5.1');
+end;
+
+procedure TNetDbTest.BuildFakeResponseAAAA(nm: ShortString; out
+ fr: TFakeDNSResponse);
+begin
+ // metadata
+ SetLength(fr.strtable, 0);
+
+ // start by building a fake header.
+ fr.hdr.ID[0] := 12;
+ fr.hdr.ID[1] := 34;
+ fr.hdr.flags1 := QF_QR or QF_RD;
+ fr.hdr.flags2 := 0;
+ fr.hdr.qdcount := 1;
+ fr.hdr.ancount := 2;
+ fr.hdr.nscount := 0;
+ fr.hdr.arcount := 0;
+
+ // Next is the query part
+ fr.qry.nm := nm;
+ fr.qry.qclass := 1;
+ fr.qry.qtype := DNSQRY_AAAA;
+
+ // now the answer RRs
+ SetLength(fr.answers,2);
+ BuildFakeRR_AAAA(fr.answers[0], nm, 300, 'fe80::3b92:3429:ff16:a3e4');
+ BuildFakeRR_AAAA(fr.answers[1], nm, 215, 'fe80::92e6:baff:fe44:ffbb');
+end;
+
+procedure TNetDbTest.BuildFakeResponseMX(nm: ShortString; out
+ fr: TFakeDNSResponse);
+begin
+ // metadata
+ SetLength(fr.strtable, 0);
+
+ // start by building a fake header.
+ fr.hdr.ID[0] := 12;
+ fr.hdr.ID[1] := 34;
+ fr.hdr.flags1 := QF_QR or QF_RD;
+ fr.hdr.flags2 := 0;
+ fr.hdr.qdcount := 1;
+ fr.hdr.ancount := 1;
+ fr.hdr.nscount := 0;
+ fr.hdr.arcount := 2;
+
+ // Next is the query part
+ fr.qry.nm := nm;
+ fr.qry.qclass := 1;
+ fr.qry.qtype := DNSQRY_MX;
+
+ // now the answer RRs
+ SetLength(fr.answers,1);
+ BuildFakeRR_MX(fr.answers[0], nm, 0, 10, 'mailer.'+FAKEFQDN);
+ // now an additional rr with the A record for the above.
+ SetLength(fr.additional, 2);
+ BuildFakeRR_A(fr.additional[0], 'mailer.'+FAKEFQDN, 0,
+ '172.16.27.238');
+ BuildFakeRR_AAAA(fr.additional[1], 'mailer.'+FAKEFQDN, 0,
+ 'fe80::3b92:3429:ff16:a3e4');
+end;
+
+procedure TNetDbTest.BuildFakeResponseSOA(nm: ShortString; out
+ fr: TFakeDNSResponse);
+begin
+ // metadata
+ SetLength(fr.strtable, 0);
+
+ // start by building a fake header.
+ fr.hdr.ID[0] := 12;
+ fr.hdr.ID[1] := 34;
+ fr.hdr.flags1 := QF_QR or QF_RD;
+ fr.hdr.flags2 := 0;
+ fr.hdr.qdcount := 1;
+ fr.hdr.ancount := 1;
+ fr.hdr.nscount := 0;
+ fr.hdr.arcount := 0;
+
+ // Next is the query part
+ fr.qry.nm := nm;
+ fr.qry.qclass := 1;
+ fr.qry.qtype := DNSQRY_SOA;
+ // now the answer RRs
+ SetLength(fr.answers,1);
+ BuildFakeRR_SOA(fr.answers[0],FAKEFQDN,33,
+ 'mn.'+FAKEFQDN,'rn.'+FAKEFQDN,76543210,
+ 123,456,789,60);
+end;
+
+procedure TNetDbTest.BuildFakeResponseCNAME(nm: ShortString; out
+ fr: TFakeDNSResponse);
+begin
+ // metadata
+ SetLength(fr.strtable, 0);
+
+ // start by building a fake header.
+ fr.hdr.ID[0] := 12;
+ fr.hdr.ID[1] := 34;
+ fr.hdr.flags1 := QF_QR or QF_RD;
+ fr.hdr.flags2 := 0;
+ fr.hdr.qdcount := 1;
+ fr.hdr.ancount := 1;
+ fr.hdr.nscount := 0;
+ fr.hdr.arcount := 0;
+
+ // Next is the query part
+ fr.qry.nm := nm;
+ fr.qry.qclass := 1;
+ fr.qry.qtype := DNSQRY_CNAME;
+
+ // now the answer RRs
+ SetLength(fr.answers,1);
+ BuildFakeRR_CNAME(fr.answers[0], nm, 300, 'fakecname.'+FAKEFQDN);
+end;
+
+procedure TNetDbTest.BuildFakeResponseNS(nm: ShortString; out
+ fr: TFakeDNSResponse);
+begin
+ // metadata
+ SetLength(fr.strtable, 0);
+
+ // start by building a fake header.
+ fr.hdr.ID[0] := 12;
+ fr.hdr.ID[1] := 34;
+ fr.hdr.flags1 := QF_QR or QF_RD;
+ fr.hdr.flags2 := 0;
+ fr.hdr.qdcount := 1;
+ fr.hdr.ancount := 1;
+ fr.hdr.nscount := 0;
+ fr.hdr.arcount := 0;
+
+ // Next is the query part
+ fr.qry.nm := nm;
+ fr.qry.qclass := 1;
+ fr.qry.qtype := DNSQRY_NS;
+
+ // now the answer RRs
+ SetLength(fr.answers,1);
+ BuildFakeRR_NS(fr.answers[0], nm, 300, 'fakens.'+FAKEFQDN);
+end;
+
+procedure TNetDbTest.BuildFakeResponsePTR(nm: ShortString; out
+ fr: TFakeDNSResponse);
+begin
+ // metadata
+ SetLength(fr.strtable, 0);
+
+ // start by building a fake header.
+ fr.hdr.ID[0] := 12;
+ fr.hdr.ID[1] := 34;
+ fr.hdr.flags1 := QF_QR or QF_RD;
+ fr.hdr.flags2 := 0;
+ fr.hdr.qdcount := 1;
+ fr.hdr.ancount := 1;
+ fr.hdr.nscount := 0;
+ fr.hdr.arcount := 0;
+
+ // Next is the query part
+ fr.qry.nm := nm;
+ fr.qry.qclass := 1;
+ fr.qry.qtype := DNSQRY_PTR;
+
+ // now the answer RRs
+ SetLength(fr.answers,1);
+ BuildFakeRR_PTR(fr.answers[0], nm, 300, 'fakeptrans.'+FAKEFQDN);
+end;
+
+procedure TNetDbTest.BuildFakeResponseTXT(nm: ShortString; out
+ fr: TFakeDNSResponse);
+var
+ txtarr: TTextArray;
+begin
+ // metadata
+ SetLength(fr.strtable, 0);
+
+ // start by building a fake header.
+ fr.hdr.ID[0] := 12;
+ fr.hdr.ID[1] := 34;
+ fr.hdr.flags1 := QF_QR or QF_RD;
+ fr.hdr.flags2 := 0;
+ fr.hdr.qdcount := 1;
+ fr.hdr.ancount := 1;
+ fr.hdr.nscount := 0;
+ fr.hdr.arcount := 0;
+
+ // Next is the query part
+ fr.qry.nm := nm;
+ fr.qry.qclass := 1;
+ fr.qry.qtype := DNSQRY_TXT;
+
+ txtarr[1] := 'v=spf1 mx a:lists.'+FAKEFQDN;
+ txtarr[2] := 'Always look on the bright side of life!';
+ // now the answer RRs
+ SetLength(fr.answers,1);
+ BuildFakeRR_TXT(fr.answers[0], nm, 300, 2, txtarr);
+end;
+
+procedure TNetDbTest.BuildFakeResponseSRV(nm: ShortString; out
+ fr: TFakeDNSResponse);
+begin
+ // metadata
+ SetLength(fr.strtable, 0);
+
+ // start by building a fake header.
+ fr.hdr.ID[0] := 12;
+ fr.hdr.ID[1] := 34;
+ fr.hdr.flags1 := QF_QR or QF_RD;
+ fr.hdr.flags2 := 0;
+ fr.hdr.qdcount := 1;
+ fr.hdr.ancount := 1;
+ fr.hdr.nscount := 0;
+ fr.hdr.arcount := 0;
+
+ // Next is the query part
+ fr.qry.nm := nm;
+ fr.qry.qclass := 1;
+ fr.qry.qtype := DNSQRY_SRV;
+ // now the answer RRs
+ SetLength(fr.answers,1);
+ BuildFakeRR_SRV(fr.answers[0],FAKEFQDN,3300,22,44,2201,'_this._that._other');
+end;
+
+{
+Test that BuildPayload puts the right values into the payload buffer.
+}
+procedure TNetDbTest.TestBuildPayloadSimple;
+var
+ Q: TQueryData;
+ R, I,J,el: Integer;
+ S: String;
+begin
+ R := BuildPayLoad(Q, FAKEFQDN, DNSQRY_A, 1);
+ // this is the expected length. Essentially, for each label, len(label)+1,
+ // then 4 bytes for the qclass and qtype, and 1 more for a 0 byte.
+ // rather than hardwire the length we calculate it so that no matter
+ // what the fake domain the test passes.
+ el := (Length(FAKEDOMAIN)+1)+(Length(FAKETLD)+1)+5;
+ AssertEquals('Payload byte count wrong:', el, R);
+ I := 0;
+ J := 0;
+ S := stringfromlabel(Q.Payload,I);
+ AssertEquals('Wrong domain name returned:',FAKEFQDN, S);
+ Move(Q.Payload[I],J,SizeOf(Word));
+ AssertEquals('Wrong query type', DNSQRY_A, NToHs(J));
+ Inc(I,2);
+ Move(Q.Payload[I],J,SizeOf(Word));
+ AssertEquals('Wrong class', 1, NToHs(J));
+end;
+
+{
+Test building a payload with an empty str.
+}
+procedure TNetDbTest.TestBuildPayloadSimpleEmpty;
+var
+ Q: TQueryData;
+ R: Integer;
+begin
+ R := BuildPayLoad(Q, '', DNSQRY_A, 1);
+ AssertEquals('Payload byte count wrong:',-1, R);
+end;
+
+{
+Test BuildQuery with a label that ends in a dot. This should be allowed.
+A dot at the end is an empty label but we must not count its 0 byte twice.
+}
+procedure TNetDbTest.TestBuildPayloadSimpleEndDot;
+var
+ Q: TQueryData;
+ R,el: Integer;
+begin
+ // this is the expected length. Essentially, for each label, len(label)+1,
+ // then 4 bytes for the qclass and qtype, and 1 more for a 0 byte.
+ // rather than hardwire the length we calculate it so that no matter
+ // what the fake domain the test passes.
+ el := (Length(FAKEDOMAIN)+1)+(Length(FAKETLD)+1)+5;
+ R := BuildPayLoad(Q, FAKEFQDN+'.', DNSQRY_A, 1);
+ AssertEquals('Payload byte count wrong:',el, R);
+end;
+
+{
+Test BuildPayload with a label that starts with a dot. This should be
+rejected outright.
+}
+procedure TNetDbTest.TestBuildPayloadSimpleStartDot;
+var
+ Q: TQueryData;
+ R: Integer;
+begin
+ R := BuildPayLoad(Q, '.'+FAKEFQDN, DNSQRY_A, 1);
+ AssertEquals('Payload byte count wrong:',-1, R);
+end;
+
+{
+Test BuildPayload with multiple dots (empty labels) in the middle of the domain
+name. This should be rejected outright.
+}
+procedure TNetDbTest.TestBuildPayloadSimpleMultipleDot;
+var
+ Q: TQueryData;
+ R: Integer;
+begin
+ R := BuildPayLoad(Q, FAKEDOMAIN+'.....'+FAKETLD, DNSQRY_A, 1);
+ AssertEquals('Payload byte count wrong:',-1, R);
+end;
+
+procedure TNetDbTest.TestDnsQueryUDP_A;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ ip: THostAddr;
+begin
+ BuildFakeResponseA(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of A records.', 2, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 2, Length(RRArr));
+ AssertEquals('RR 0 is not an A RR.',DNSQRY_A, RRarr[0].RRMeta.Atype);
+ AssertEquals('RR 1 is not an A RR.', DNSQRY_A, RRarr[1].RRMeta.Atype);
+ AssertEquals('Wrong A record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+ AssertEquals('Wrong A record name for RR 1', FAKEFQDN,
+ RRArr[1].RRName);
+ AssertTrue('Did not get RR A data.', DNSRRGetA(RRArr[0], qd.Payload, ip));
+ AssertEquals('Wrong ip for A.', '127.0.0.1', HostAddrToStr(ip));
+ AssertTrue('Did not get RR A data.', DNSRRGetA(RRArr[1], qd.Payload, ip));
+ AssertEquals('Wrong ip for A.', '127.0.5.1', HostAddrToStr(ip));
+end;
+
+procedure TNetDbTest.TestDnsQueryTCP_A;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ ip: THostAddr;
+begin
+ BuildFakeResponseA(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of A records.', 2, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 2, Length(RRArr));
+ AssertEquals('RR 0 is not an A RR.',DNSQRY_A, RRarr[0].RRMeta.Atype);
+ AssertEquals('RR 1 is not an A RR.', DNSQRY_A, RRarr[1].RRMeta.Atype);
+ AssertEquals('Wrong A record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+ AssertEquals('Wrong A record name for RR 1', FAKEFQDN,
+ RRArr[1].RRName);
+ AssertTrue('Did not get RR A data.', DNSRRGetA(RRArr[0], qd.Payload, ip));
+ AssertEquals('Wrong ip for A.', '127.0.0.1', HostAddrToStr(ip));
+ AssertTrue('Did not get RR A data.', DNSRRGetA(RRArr[1], qd.Payload, ip));
+ AssertEquals('Wrong ip for A.', '127.0.5.1', HostAddrToStr(ip));
+end;
+
+procedure TNetDbTest.TestDnsQueryCompressUDP_A;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ ip: THostAddr;
+begin
+ BuildFakeResponseA(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to compressed querydata',
+ BuildQueryData(fakeresp, qd, anslen, True));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of A records.', 2, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 2, Length(RRArr));
+ AssertEquals('RR 0 is not an A RR.',DNSQRY_A, RRarr[0].RRMeta.Atype);
+ AssertEquals('RR 1 is not an A RR.', DNSQRY_A, RRarr[1].RRMeta.Atype);
+ AssertEquals('Wrong A record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+ AssertEquals('Wrong A record name for RR 1', FAKEFQDN,
+ RRArr[1].RRName);
+ AssertTrue('Did not get RR A data.', DNSRRGetA(RRArr[0], qd.Payload, ip));
+ AssertEquals('Wrong ip for A.', '127.0.0.1', HostAddrToStr(ip));
+ AssertTrue('Did not get RR A data.', DNSRRGetA(RRArr[1], qd.Payload, ip));
+ AssertEquals('Wrong ip for A.', '127.0.5.1', HostAddrToStr(ip));
+end;
+
+procedure TNetDbTest.TestDnsQueryCompressTCP_A;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ ip: THostAddr;
+begin
+ BuildFakeResponseA(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to compressed querydata',
+ BuildQueryData(fakeresp, qd, anslen, True));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of A records.', 2, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 2, Length(RRArr));
+ AssertEquals('RR 0 is not an A RR.',DNSQRY_A, RRarr[0].RRMeta.Atype);
+ AssertEquals('RR 1 is not an A RR.', DNSQRY_A, RRarr[1].RRMeta.Atype);
+ AssertEquals('Wrong A record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+ AssertEquals('Wrong A record name for RR 1', FAKEFQDN,
+ RRArr[1].RRName);
+ AssertTrue('Did not get RR A data.', DNSRRGetA(RRArr[0], qd.Payload, ip));
+ AssertEquals('Wrong ip for A.', '127.0.0.1', HostAddrToStr(ip));
+ AssertTrue('Did not get RR A data.', DNSRRGetA(RRArr[1], qd.Payload, ip));
+ AssertEquals('Wrong ip for A.', '127.0.5.1', HostAddrToStr(ip));
+end;
+
+procedure TNetDbTest.TestDnsQueryUDP_AAAA;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ ip: THostAddr6;
+begin
+ BuildFakeResponseAAAA(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of AAAA records.', 2, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 2, Length(RRArr));
+ AssertEquals('RR 0 is not an AAAA RR.',DNSQRY_AAAA, RRarr[0].RRMeta.Atype);
+ AssertEquals('RR 1 is not an AAAA RR.', DNSQRY_AAAA, RRarr[1].RRMeta.Atype);
+ AssertEquals('Wrong AAAA record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+ AssertEquals('Wrong AAAA record name for RR 1', FAKEFQDN,
+ RRArr[1].RRName);
+ AssertTrue('Did not get RR AAAA data.', DNSRRGetAAAA(RRArr[0], qd.Payload, ip));
+ AssertEquals('Wrong ip for AAAA.', 'FE80::3B92:3429:FF16:A3E4', HostAddrToStr6(ip));
+ AssertTrue('Did not get RR AAAA data.', DNSRRGetAAAA(RRArr[1], qd.Payload, ip));
+ AssertEquals('Wrong ip for AAAA.', 'FE80::92E6:BAFF:FE44:FFBB', HostAddrToStr6(ip));
+end;
+
+procedure TNetDbTest.TestDnsQueryTCP_AAAA;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ ip: THostAddr6;
+begin
+ BuildFakeResponseAAAA(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of AAAA records.', 2, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 2, Length(RRArr));
+ AssertEquals('RR 0 is not an AAAA RR.',DNSQRY_AAAA, RRarr[0].RRMeta.Atype);
+ AssertEquals('RR 1 is not an AAAA RR.', DNSQRY_AAAA, RRarr[1].RRMeta.Atype);
+ AssertEquals('Wrong AAAA record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+ AssertEquals('Wrong AAAA record name for RR 1', FAKEFQDN,
+ RRArr[1].RRName);
+ AssertTrue('Did not get RR AAAA data.', DNSRRGetAAAA(RRArr[0],
+ qd.Payload, ip));
+ AssertEquals('Wrong ip for AAAA.', 'FE80::3B92:3429:FF16:A3E4',
+ HostAddrToStr6(ip));
+ AssertTrue('Did not get RR AAAA data.', DNSRRGetAAAA(RRArr[1],
+ qd.Payload, ip));
+ AssertEquals('Wrong ip for AAAA.', 'FE80::92E6:BAFF:FE44:FFBB',
+ HostAddrToStr6(ip));
+end;
+
+procedure TNetDbTest.TestDnsQueryCompressUDP_AAAA;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ ip: THostAddr6;
+begin
+ BuildFakeResponseAAAA(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to compressed querydata',
+ BuildQueryData(fakeresp, qd, anslen, True));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of AAAA records.', 2, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 2, Length(RRArr));
+ AssertEquals('RR 0 is not an AAAA RR.',DNSQRY_AAAA, RRarr[0].RRMeta.Atype);
+ AssertEquals('RR 1 is not an AAAA RR.', DNSQRY_AAAA, RRarr[1].RRMeta.Atype);
+ AssertEquals('Wrong AAAA record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+ AssertEquals('Wrong AAAA record name for RR 1', FAKEFQDN,
+ RRArr[1].RRName);
+ AssertTrue('Did not get RR AAAA data.', DNSRRGetAAAA(RRArr[0],
+ qd.Payload, ip));
+ AssertEquals('Wrong ip for AAAA.', 'FE80::3B92:3429:FF16:A3E4',
+ HostAddrToStr6(ip));
+ AssertTrue('Did not get RR AAAA data.', DNSRRGetAAAA(RRArr[1],
+ qd.Payload, ip));
+ AssertEquals('Wrong ip for AAAA.', 'FE80::92E6:BAFF:FE44:FFBB',
+ HostAddrToStr6(ip));
+end;
+
+procedure TNetDbTest.TestDnsQueryCompressTCP_AAAA;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ ip: THostAddr6;
+begin
+ BuildFakeResponseAAAA(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to compressed querydata',
+ BuildQueryData(fakeresp, qd, anslen, True));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of AAAA records.', 2, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 2, Length(RRArr));
+ AssertEquals('RR 0 is not an AAAA RR.',DNSQRY_AAAA, RRarr[0].RRMeta.Atype);
+ AssertEquals('RR 1 is not an AAAA RR.', DNSQRY_AAAA, RRarr[1].RRMeta.Atype);
+ AssertEquals('Wrong AAAA record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+ AssertEquals('Wrong AAAA record name for RR 1', FAKEFQDN,
+ RRArr[1].RRName);
+ AssertTrue('Did not get RR AAAA data.', DNSRRGetAAAA(RRArr[0],
+ qd.Payload, ip));
+ AssertEquals('Wrong ip for AAAA.', 'FE80::3B92:3429:FF16:A3E4',
+ HostAddrToStr6(ip));
+ AssertTrue('Did not get RR AAAA data.', DNSRRGetAAAA(RRArr[1],
+ qd.Payload, ip));
+ AssertEquals('Wrong ip for AAAA.', 'FE80::92E6:BAFF:FE44:FFBB',
+ HostAddrToStr6(ip));
+end;
+
+procedure TNetDbTest.TestDnsQueryUDP_MX;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ mxrec: TDNSRR_MX;
+ ip: THostAddr;
+ ip6: THostAddr6;
+begin
+ BuildFakeResponseMX(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of MX records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an MX RR.',DNSQRY_MX, RRarr[0].RRMeta.Atype);
+
+ AssertEquals('Wrong record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+
+ AssertTrue('Did not get RR MX data.', DNSRRGetMX(RRArr[0], qd.Payload, mxrec));
+ AssertEquals('Wrong MX hostname', 'mailer.'+FAKEFQDN,
+ mxrec.exchange);
+ AssertEquals('Wrong MX preference', 10, mxrec.preference);
+
+ AssertEquals('Should be 2 additional RR records.',2,NToHs(qd.h.arcount));
+ RRArr := GetRRrecords(qd.Payload, ansstart, NToHs(qd.h.arcount));
+ AssertEquals('Wrong number of resource records.', 2, Length(RRArr));
+ AssertEquals('RR 0 is not an A RR.',DNSQRY_A, RRarr[0].RRMeta.Atype);
+ AssertEquals('RR 1 is not an AAAA RR.', DNSQRY_AAAA, RRarr[1].RRMeta.Atype);
+ AssertTrue('Did not get RR A data.', DNSRRGetA(RRArr[0], qd.Payload, ip));
+ AssertTrue('Did not get RR AAAA data.', DNSRRGetAAAA(RRArr[1], qd.Payload, ip6));
+
+ AssertEquals('Wrong ip for A.', '172.16.27.238', HostAddrToStr(ip));
+ AssertEquals('Wrong ip for AAAA.', 'FE80::3B92:3429:FF16:A3E4',
+ HostAddrToStr6(ip6));
+end;
+
+procedure TNetDbTest.TestDnsQueryTCP_MX;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ mxrec: TDNSRR_MX;
+ ip: THostAddr;
+ ip6: THostAddr6;
+begin
+ BuildFakeResponseMX(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of MX records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an MX RR.',DNSQRY_MX, RRarr[0].RRMeta.Atype);
+
+ AssertEquals('Wrong record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+
+ AssertTrue('Did not get RR MX data.', DNSRRGetMX(RRArr[0], qd.Payload, mxrec));
+ AssertEquals('Wrong MX hostname', 'mailer.'+FAKEFQDN,
+ mxrec.exchange);
+ AssertEquals('Wrong MX preference', 10, mxrec.preference);
+
+ AssertEquals('Should be 2 additional RR records.',2,NToHs(qd.h.arcount));
+ RRArr := GetRRrecords(qd.Payload, ansstart, NToHs(qd.h.arcount));
+ AssertEquals('Wrong number of resource records.', 2, Length(RRArr));
+ AssertEquals('RR 0 is not an A RR.',DNSQRY_A, RRarr[0].RRMeta.Atype);
+ AssertEquals('RR 1 is not an AAAA RR.', DNSQRY_AAAA, RRarr[1].RRMeta.Atype);
+ AssertTrue('Did not get RR A data.', DNSRRGetA(RRArr[0], qd.Payload, ip));
+ AssertTrue('Did not get RR AAAA data.', DNSRRGetAAAA(RRArr[1], qd.Payload, ip6));
+
+ AssertEquals('Wrong ip for A.', '172.16.27.238', HostAddrToStr(ip));
+ AssertEquals('Wrong ip for AAAA.', 'FE80::3B92:3429:FF16:A3E4',
+ HostAddrToStr6(ip6));
+end;
+
+procedure TNetDbTest.TestDnsQueryCompressUDP_MX;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ mxrec: TDNSRR_MX;
+ ip: THostAddr;
+ ip6: THostAddr6;
+begin
+ BuildFakeResponseMX(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to compressed querydata',
+ BuildQueryData(fakeresp, qd, anslen, True));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of MX records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an MX RR.',DNSQRY_MX, RRarr[0].RRMeta.Atype);
+
+ AssertEquals('Wrong record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+
+ AssertTrue('Did not get RR MX data.', DNSRRGetMX(RRArr[0], qd.Payload, mxrec));
+ AssertEquals('Wrong MX hostname', 'mailer.'+FAKEFQDN,
+ mxrec.exchange);
+ AssertEquals('Wrong MX preference', 10, mxrec.preference);
+
+ AssertEquals('Should be 2 additional RR records.',2,NToHs(qd.h.arcount));
+ RRArr := GetRRrecords(qd.Payload, ansstart, NToHs(qd.h.arcount));
+ AssertEquals('Wrong number of resource records.', 2, Length(RRArr));
+ AssertEquals('RR 0 is not an A RR.',DNSQRY_A, RRarr[0].RRMeta.Atype);
+ AssertEquals('RR 1 is not an AAAA RR.', DNSQRY_AAAA, RRarr[1].RRMeta.Atype);
+ AssertTrue('Did not get RR A data.', DNSRRGetA(RRArr[0], qd.Payload, ip));
+ AssertTrue('Did not get RR AAAA data.', DNSRRGetAAAA(RRArr[1], qd.Payload,
+ ip6));
+
+ AssertEquals('Wrong ip for A.', '172.16.27.238', HostAddrToStr(ip));
+ AssertEquals('Wrong ip for AAAA.', 'FE80::3B92:3429:FF16:A3E4',
+ HostAddrToStr6(ip6));
+end;
+
+procedure TNetDbTest.TestDnsQueryCompressTCP_MX;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ mxrec: TDNSRR_MX;
+ ip: THostAddr;
+ ip6: THostAddr6;
+begin
+ BuildFakeResponseMX(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to compressed querydata',
+ BuildQueryData(fakeresp, qd, anslen, True));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of MX records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an MX RR.',DNSQRY_MX, RRarr[0].RRMeta.Atype);
+
+ AssertEquals('Wrong record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+
+ AssertTrue('Did not get RR MX data.', DNSRRGetMX(RRArr[0], qd.Payload, mxrec));
+ AssertEquals('Wrong MX hostname', 'mailer.'+FAKEFQDN,
+ mxrec.exchange);
+ AssertEquals('Wrong MX preference', 10, mxrec.preference);
+
+ AssertEquals('Should be 2 additional RR records.',2,NToHs(qd.h.arcount));
+ RRArr := GetRRrecords(qd.Payload, ansstart, NToHs(qd.h.arcount));
+ AssertEquals('Wrong number of resource records.', 2, Length(RRArr));
+ AssertEquals('RR 0 is not an A RR.',DNSQRY_A, RRarr[0].RRMeta.Atype);
+ AssertEquals('RR 1 is not an AAAA RR.', DNSQRY_AAAA, RRarr[1].RRMeta.Atype);
+ AssertTrue('Did not get RR A data.', DNSRRGetA(RRArr[0], qd.Payload, ip));
+ AssertTrue('Did not get RR AAAA data.', DNSRRGetAAAA(RRArr[1], qd.Payload,
+ ip6));
+
+ AssertEquals('Wrong ip for A.', '172.16.27.238', HostAddrToStr(ip));
+ AssertEquals('Wrong ip for AAAA.', 'FE80::3B92:3429:FF16:A3E4',
+ HostAddrToStr6(ip6));
+end;
+
+procedure TNetDbTest.TestDnsQueryUDP_SOA;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ soarec: TDNSRR_SOA;
+begin
+ BuildFakeResponseSOA(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of SOA records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an SOA RR.',DNSQRY_SOA, RRarr[0].RRMeta.Atype);
+
+ AssertEquals('Wrong record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+
+ AssertTrue('Did not get RR SOA data.', DNSRRGetSOA(RRArr[0], qd.Payload,
+ soarec));
+ AssertEquals('Wrong mname hostname', 'mn.'+FAKEFQDN,
+ soarec.mname);
+ AssertEquals('Wrong rname hostname', 'rn.'+FAKEFQDN,
+ soarec.rname);
+ AssertEquals('Wrong SOA serial', 76543210, soarec.serial);
+ AssertEquals('Wrong SOA refresh', 123, soarec.refresh);
+ AssertEquals('Wrong SOA retry', 456, soarec.retry);
+ AssertEquals('Wrong SOA expire', 789, soarec.expire);
+ AssertEquals('Wrong SOA min', 60, soarec.min);
+end;
+
+procedure TNetDbTest.TestDnsQueryTCP_SOA;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ soarec: TDNSRR_SOA;
+begin
+ BuildFakeResponseSOA(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of SOA records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an SOA RR.',DNSQRY_SOA, RRarr[0].RRMeta.Atype);
+
+ AssertEquals('Wrong record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+
+ AssertTrue('Did not get RR SOA data.', DNSRRGetSOA(RRArr[0], qd.Payload,
+ soarec));
+ AssertEquals('Wrong mname hostname', 'mn.'+FAKEFQDN,
+ soarec.mname);
+ AssertEquals('Wrong rname hostname', 'rn.'+FAKEFQDN,
+ soarec.rname);
+ AssertEquals('Wrong SOA serial', 76543210, soarec.serial);
+ AssertEquals('Wrong SOA refresh', 123, soarec.refresh);
+ AssertEquals('Wrong SOA retry', 456, soarec.retry);
+ AssertEquals('Wrong SOA expire', 789, soarec.expire);
+ AssertEquals('Wrong SOA min', 60, soarec.min);
+end;
+
+procedure TNetDbTest.TestDnsQueryCompressUDP_SOA;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ soarec: TDNSRR_SOA;
+begin
+ BuildFakeResponseSOA(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen, True));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of SOA records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an SOA RR.',DNSQRY_SOA, RRarr[0].RRMeta.Atype);
+
+ AssertEquals('Wrong record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+
+ AssertTrue('Did not get RR SOA data.', DNSRRGetSOA(RRArr[0], qd.Payload,
+ soarec));
+ AssertEquals('Wrong mname hostname', 'mn.'+FAKEFQDN,
+ soarec.mname);
+ AssertEquals('Wrong rname hostname', 'rn.'+FAKEFQDN,
+ soarec.rname);
+ AssertEquals('Wrong SOA serial', 76543210, soarec.serial);
+ AssertEquals('Wrong SOA refresh', 123, soarec.refresh);
+ AssertEquals('Wrong SOA retry', 456, soarec.retry);
+ AssertEquals('Wrong SOA expire', 789, soarec.expire);
+ AssertEquals('Wrong SOA min', 60, soarec.min);
+end;
+
+procedure TNetDbTest.TestDnsQueryCompressTCP_SOA;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ soarec: TDNSRR_SOA;
+begin
+ BuildFakeResponseSOA(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to compressed querydata',
+ BuildQueryData(fakeresp, qd, anslen, True));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of SOA records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an SOA RR.',DNSQRY_SOA, RRarr[0].RRMeta.Atype);
+
+ AssertEquals('Wrong record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+
+ AssertTrue('Did not get RR SOA data.', DNSRRGetSOA(RRArr[0], qd.Payload,
+ soarec));
+ AssertEquals('Wrong mname hostname', 'mn.'+FAKEFQDN,
+ soarec.mname);
+ AssertEquals('Wrong rname hostname', 'rn.'+FAKEFQDN,
+ soarec.rname);
+ AssertEquals('Wrong SOA serial', 76543210, soarec.serial);
+ AssertEquals('Wrong SOA refresh', 123, soarec.refresh);
+ AssertEquals('Wrong SOA retry', 456, soarec.retry);
+ AssertEquals('Wrong SOA expire', 789, soarec.expire);
+ AssertEquals('Wrong SOA min', 60, soarec.min);
+end;
+
+procedure TNetDbTest.TestDnsQueryUDP_CNAME;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ s: TDNSDomainName;
+begin
+ BuildFakeResponseCNAME(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of CNAME records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an CNAME RR.',DNSQRY_CNAME, RRarr[0].RRMeta.Atype);
+ AssertEquals('Wrong CNAME record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+ AssertTrue('Did not get RR CNAME data.', DNSRRGetCNAME(RRArr[0], qd.Payload, s));
+ AssertEquals('Wrong CNAME.', 'fakecname.'+FAKEFQDN, s);
+end;
+
+procedure TNetDbTest.TestDnsQueryTCP_CNAME;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ s: TDNSDomainName;
+begin
+ BuildFakeResponseCNAME(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of CNAME records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an CNAME RR.',DNSQRY_CNAME, RRarr[0].RRMeta.Atype);
+ AssertEquals('Wrong CNAME record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+ AssertTrue('Did not get RR CNAME data.', DNSRRGetCNAME(RRArr[0], qd.Payload, s));
+ AssertEquals('Wrong CNAME.', 'fakecname.'+FAKEFQDN, s);
+end;
+
+procedure TNetDbTest.TestDnsQueryCompressUDP_CNAME;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ s: TDNSDomainName;
+begin
+ BuildFakeResponseCNAME(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to compressed querydata',
+ BuildQueryData(fakeresp, qd, anslen, True));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of CNAME records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an CNAME RR.',DNSQRY_CNAME, RRarr[0].RRMeta.Atype);
+ AssertEquals('Wrong CNAME record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+ AssertTrue('Did not get RR CNAME data.', DNSRRGetCNAME(RRArr[0], qd.Payload, s));
+ AssertEquals('Wrong CNAME.', 'fakecname.'+FAKEFQDN, s);
+end;
+
+procedure TNetDbTest.TestDnsQueryCompressTCP_CNAME;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ s: TDNSDomainName;
+begin
+ BuildFakeResponseCNAME(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to compressed querydata',
+ BuildQueryData(fakeresp, qd, anslen, True));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of CNAME records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an CNAME RR.',DNSQRY_CNAME, RRarr[0].RRMeta.Atype);
+ AssertEquals('Wrong CNAME record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+ AssertTrue('Did not get RR CNAME data.', DNSRRGetCNAME(RRArr[0], qd.Payload,
+ s));
+ AssertEquals('Wrong CNAME.', 'fakecname.'+FAKEFQDN, s);
+end;
+
+procedure TNetDbTest.TestDnsQueryUDP_NS;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ s: TDNSDomainName;
+begin
+ BuildFakeResponseNS(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of NS records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an NS RR.',DNSQRY_NS, RRarr[0].RRMeta.Atype);
+ AssertEquals('Wrong NS record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+ AssertTrue('Did not get RR NS data.', DNSRRGetNS(RRArr[0], qd.Payload, s));
+ AssertEquals('Wrong NS.', 'fakens.'+FAKEFQDN, s);
+end;
+
+procedure TNetDbTest.TestDnsQueryTCP_NS;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ s: TDNSDomainName;
+begin
+ BuildFakeResponseNS(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of NS records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an NS RR.',DNSQRY_NS, RRarr[0].RRMeta.Atype);
+ AssertEquals('Wrong NS record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+ AssertTrue('Did not get RR NS data.', DNSRRGetNS(RRArr[0], qd.Payload, s));
+ AssertEquals('Wrong NS.', 'fakens.'+FAKEFQDN, s);
+end;
+
+procedure TNetDbTest.TestDnsQueryCompressUDP_NS;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ s: TDNSDomainName;
+begin
+ BuildFakeResponseNS(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to compressed querydata',
+ BuildQueryData(fakeresp, qd, anslen, True));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of NS records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an NS RR.',DNSQRY_NS, RRarr[0].RRMeta.Atype);
+ AssertEquals('Wrong NS record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+ AssertTrue('Did not get RR NS data.', DNSRRGetNS(RRArr[0], qd.Payload, s));
+ AssertEquals('Wrong NS.', 'fakens.'+FAKEFQDN, s);
+end;
+
+procedure TNetDbTest.TestDnsQueryCompressTCP_NS;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ s: TDNSDomainName;
+begin
+ BuildFakeResponseNS(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to compressed querydata',
+ BuildQueryData(fakeresp, qd, anslen, True));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of NS records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an NS RR.',DNSQRY_NS, RRarr[0].RRMeta.Atype);
+ AssertEquals('Wrong NS record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+ AssertTrue('Did not get RR NS data.', DNSRRGetNS(RRArr[0], qd.Payload, s));
+ AssertEquals('Wrong NS.', 'fakens.'+FAKEFQDN, s);
+end;
+
+procedure TNetDbTest.TestDnsQueryUDP_PTR;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ s: TDNSDomainName;
+begin
+ // the str passed in to this function doesn't really matter, but using
+ // a proper in-addr.arpa domain helps keep it clear what we're testing.
+ BuildFakeResponsePTR('0.5.0.127.in-addr.arpa', fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of PTR records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an PTR RR.',DNSQRY_PTR, RRarr[0].RRMeta.Atype);
+ AssertEquals('Wrong PTR record name for RR 0', '0.5.0.127.in-addr.arpa',
+ RRArr[0].RRName);
+ AssertTrue('Did not get RR PTR data.', DNSRRGetPTR(RRArr[0], qd.Payload, s));
+ AssertEquals('Wrong PTR.', 'fakeptrans.'+FAKEFQDN, s);
+end;
+
+procedure TNetDbTest.TestDnsQueryTCP_PTR;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ s: TDNSDomainName;
+begin
+ // the str passed in to this function doesn't really matter, but using
+ // a proper in-addr.arpa domain helps keep it clear what we're testing.
+ BuildFakeResponsePTR('0.5.0.127.in-addr.arpa', fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of PTR records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an PTR RR.',DNSQRY_PTR, RRarr[0].RRMeta.Atype);
+ AssertEquals('Wrong PTR record name for RR 0', '0.5.0.127.in-addr.arpa',
+ RRArr[0].RRName);
+ AssertTrue('Did not get RR PTR data.', DNSRRGetPTR(RRArr[0], qd.Payload, s));
+ AssertEquals('Wrong PTR.', 'fakeptrans.'+FAKEFQDN, s);
+end;
+
+procedure TNetDbTest.TestDnsQueryCompressUDP_PTR;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ s: TDNSDomainName;
+begin
+ // the str passed in to this function doesn't really matter, but using
+ // a proper in-addr.arpa domain helps keep it clear what we're testing.
+ BuildFakeResponsePTR('0.5.0.127.in-addr.arpa', fakeresp);
+ AssertTrue('Unable to convert fake dns response to compressed querydata',
+ BuildQueryData(fakeresp, qd, anslen, True));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of PTR records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an PTR RR.',DNSQRY_PTR, RRarr[0].RRMeta.Atype);
+ AssertEquals('Wrong PTR record name for RR 0', '0.5.0.127.in-addr.arpa',
+ RRArr[0].RRName);
+ AssertTrue('Did not get RR PTR data.', DNSRRGetPTR(RRArr[0], qd.Payload, s));
+ AssertEquals('Wrong PTR.', 'fakeptrans.'+FAKEFQDN, s);
+end;
+
+procedure TNetDbTest.TestDnsQueryCompressTCP_PTR;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ s: TDNSDomainName;
+begin
+ // the str passed in to this function doesn't really matter, but using
+ // a proper in-addr.arpa domain helps keep it clear what we're testing.
+ BuildFakeResponsePTR('0.5.0.127.in-addr.arpa', fakeresp);
+ AssertTrue('Unable to convert fake dns response to compressed querydata',
+ BuildQueryData(fakeresp, qd, anslen, True));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of PTR records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an PTR RR.',DNSQRY_PTR, RRarr[0].RRMeta.Atype);
+ AssertEquals('Wrong PTR record name for RR 0', '0.5.0.127.in-addr.arpa',
+ RRArr[0].RRName);
+ AssertTrue('Did not get RR PTR data.', DNSRRGetPTR(RRArr[0], qd.Payload, s));
+ AssertEquals('Wrong PTR.', 'fakeptrans.'+FAKEFQDN, s);
+end;
+
+procedure TNetDbTest.TestDnsQueryUDP_TXT;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ s: AnsiString;
+begin
+ s := '';
+ BuildFakeResponseTXT(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of TXT records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not a TXT RR.',DNSQRY_TXT, RRarr[0].RRMeta.Atype);
+ AssertEquals('Wrong TXT record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+ AssertTrue('Did not get RR TXT data.', DNSRRGetText(RRArr[0], qd.Payload, s));
+ AssertEquals(
+ 'v=spf1 mx a:lists.'+FAKEFQDN+'Always look on the bright side of life!',
+ s);
+end;
+
+procedure TNetDbTest.TestDnsQueryTCP_TXT;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ s: AnsiString;
+begin
+ s := '';
+ BuildFakeResponseTXT(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of TXT records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not a TXT RR.',DNSQRY_TXT, RRarr[0].RRMeta.Atype);
+ AssertEquals('Wrong TXT record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+ AssertTrue('Did not get RR TXT data.', DNSRRGetText(RRArr[0], qd.Payload, s));
+ AssertEquals(
+ 'v=spf1 mx a:lists.'+FAKEFQDN+'Always look on the bright side of life!',
+ s);
+end;
+
+procedure TNetDbTest.TestDnsQueryCompressUDP_TXT;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ s: AnsiString;
+begin
+ s := '';
+ BuildFakeResponseTXT(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to compressed querydata',
+ BuildQueryData(fakeresp, qd, anslen, True));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of TXT records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not a TXT RR.',DNSQRY_TXT, RRarr[0].RRMeta.Atype);
+ AssertEquals('Wrong TXT record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+ AssertTrue('Did not get RR TXT data.', DNSRRGetText(RRArr[0], qd.Payload, s));
+ AssertEquals(
+ 'v=spf1 mx a:lists.'+FAKEFQDN+'Always look on the bright side of life!',
+ s);
+end;
+
+procedure TNetDbTest.TestDnsQueryCompressTCP_TXT;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ s: AnsiString;
+begin
+ s := '';
+ BuildFakeResponseTXT(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to compressed querydata',
+ BuildQueryData(fakeresp, qd, anslen, True));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of TXT records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not a TXT RR.',DNSQRY_TXT, RRarr[0].RRMeta.Atype);
+ AssertEquals('Wrong TXT record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+ AssertTrue('Did not get RR TXT data.', DNSRRGetText(RRArr[0], qd.Payload, s));
+ AssertEquals(
+ 'v=spf1 mx a:lists.'+FAKEFQDN+'Always look on the bright side of life!',
+ s);
+end;
+
+procedure TNetDbTest.TestDnsQueryUDP_SRV;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ srvrec: TDNSRR_SRV;
+begin
+ BuildFakeResponseSRV(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of SRV records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an SRV RR.',DNSQRY_SRV, RRarr[0].RRMeta.Atype);
+
+ AssertEquals('Wrong record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+
+ AssertTrue('Did not get RR SRV data.', DNSRRGetSRV(RRArr[0], qd.Payload,
+ srvrec));
+ AssertEquals('Wrong SRV priority', 22, srvrec.priority);
+ AssertEquals('Wrong SRV weight', 44, srvrec.weight);
+ AssertEquals('Wrong SRV port', 2201, srvrec.port);
+
+ AssertEquals('Wrong SRV hostname', '_this._that._other', srvrec.target);
+end;
+
+procedure TNetDbTest.TestDnsQueryTCP_SRV;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ srvrec: TDNSRR_SRV;
+begin
+ BuildFakeResponseSRV(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of SRV records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an SRV RR.',DNSQRY_SRV, RRarr[0].RRMeta.Atype);
+
+ AssertEquals('Wrong record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+
+ AssertTrue('Did not get RR SOA data.', DNSRRGetSRV(RRArr[0], qd.Payload,
+ srvrec));
+ AssertEquals('Wrong SRV priority', 22, srvrec.priority);
+ AssertEquals('Wrong SRV weight', 44, srvrec.weight);
+ AssertEquals('Wrong SRV port', 2201, srvrec.port);
+
+ AssertEquals('Wrong SRV hostname', '_this._that._other', srvrec.target);
+end;
+
+procedure TNetDbTest.TestDnsQueryCompressUDP_SRV;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ srvrec: TDNSRR_SRV;
+begin
+ BuildFakeResponseSRV(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to compressed querydata',
+ BuildQueryData(fakeresp, qd, anslen, True));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of SRV records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an SRV RR.',DNSQRY_SRV, RRarr[0].RRMeta.Atype);
+
+ AssertEquals('Wrong record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+
+ AssertTrue('Did not get RR SRV data.', DNSRRGetSRV(RRArr[0], qd.Payload,
+ srvrec));
+ AssertEquals('Wrong SRV priority', 22, srvrec.priority);
+ AssertEquals('Wrong SRV weight', 44, srvrec.weight);
+ AssertEquals('Wrong SRV port', 2201, srvrec.port);
+
+ AssertEquals('Wrong SRV hostname', '_this._that._other', srvrec.target);
+end;
+
+procedure TNetDbTest.TestDnsQueryCompressTCP_SRV;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ srvrec: TDNSRR_SRV;
+begin
+ BuildFakeResponseSRV(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to compressed querydata',
+ BuildQueryData(fakeresp, qd, anslen, True));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of SRV records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an SRV RR.',DNSQRY_SRV, RRarr[0].RRMeta.Atype);
+
+ AssertEquals('Wrong record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+
+ AssertTrue('Did not get RR SOA data.', DNSRRGetSRV(RRArr[0], qd.Payload,
+ srvrec));
+ AssertEquals('Wrong SRV priority', 22, srvrec.priority);
+ AssertEquals('Wrong SRV weight', 44, srvrec.weight);
+ AssertEquals('Wrong SRV port', 2201, srvrec.port);
+
+ AssertEquals('Wrong SRV hostname', '_this._that._other', srvrec.target);
+end;
+
+{
+This test is of debatable value, as it only detects truncation if the buffer
+contents are zeroed which gives an invalid RR type.
+}
+procedure TNetDbTest.TestDnsQueryTruncateRR_UDP_A;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+begin
+ BuildFakeResponseA(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildTruncatedQueryData(fakeresp, qd, anslen,40));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ // the header says there are 2 A records, but it's a trap!
+ AssertEquals('Wrong number of A records.', 2, qd.h.ancount);
+ // truncation of buffer means this call returns 0 RRs.
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of RRs', 0, Length(RRArr));
+end;
+
+procedure TNetDbTest.TestDnsRRBufferEdgeA;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ ip: THostAddr;
+begin
+ BuildFakeResponseA(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of A records.', 2, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+
+ // Change start position for RR[0] to end of buffer - 4
+ RRArr[0].RDataSt := Length(qd.Payload) - RRArr[0].RRMeta.RDLength;
+ qd.Payload[Length(qd.Payload)-1] := $AA; // sentinel marker we can look for
+
+ AssertTrue('Did not get RR A data.', DNSRRGetA(RRArr[0], qd.Payload, ip));
+ AssertEquals('Wrong ip for A.', '0.0.0.170', HostAddrToStr(ip));
+end;
+
+procedure TNetDbTest.TestDnsRRBufferPastEdgeA;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ ip: THostAddr;
+begin
+ BuildFakeResponseA(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of A records.', 2, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+
+ // Change start position for RR[0] to end of buffer - 3
+ RRArr[0].RDataSt := Length(qd.Payload) - (RRArr[0].RRMeta.RDLength - 3);
+ AssertFalse('Got RR A data.', DNSRRGetA(RRArr[0], qd.Payload, ip));
+end;
+
+{
+Test that we read the AAAA right at the buffer edge, with the last byte
+being a special value we can test for.
+}
+procedure TNetDbTest.TestDnsRRBufferEdgeAAAA;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ ip: THostAddr6;
+begin
+ BuildFakeResponseAAAA(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of AAAA records.', 2, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ // Change start position for RR[0]
+ RRArr[0].RDataSt := Length(qd.Payload) - SizeOf(THostAddr6);
+ qd.Payload[Length(qd.Payload)-1] := $AA;
+ AssertTrue('Got RR AAAA data.', DNSRRGetAAAA(RRArr[0], qd.Payload, ip));
+ AssertEquals($AA, ip.u6_addr8[15]);
+end;
+
+{
+Attempt to read an AAAA that goes past the end of the buffer.
+}
+procedure TNetDbTest.TestDNsRRBufferPastEdgeAAAA;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ ip: THostAddr6;
+begin
+ BuildFakeResponseAAAA(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of AAAA records.', 2, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ // Change start position for RR[0]. attempting to read 16 bytes
+ // from this position will pass the end of the buffer.
+ RRArr[0].RDataSt := Length(qd.Payload) - (SizeOf(THostAddr6)-1);
+ qd.Payload[Length(qd.Payload)-1] := $AA;
+ AssertFalse('Got RR AAAA data.', DNSRRGetAAAA(RRArr[0], qd.Payload, ip));
+end;
+
+{
+Test reading an MX RR that terminates on the last byte of the buffer.
+}
+procedure TNetDbTest.TestDnsRRBufferEdgeMX;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart, oldstart: Word;
+ RRArr: TRRNameDataArray;
+ fmx: TDNSRR_MX;
+begin
+ BuildFakeResponseMX(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of MX records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+
+ // move the MX RR bytes to the end of the payload buffer.
+ oldstart := RRArr[0].RDataSt;
+ RRArr[0].RDataSt := Length(qd.Payload) - RRArr[0].RRMeta.RDLength;
+ CopyBytesTo(qd.Payload, oldstart, RRArr[0].RDataSt, RRArr[0].RRMeta.RDLength);
+
+ AssertTrue('Got RR MX data.', DNSRRGetMX(RRArr[0], qd.Payload, fmx));
+ AssertEquals('Wrong MX hostname', 'mailer.'+FAKEFQDN,
+ fmx.exchange);
+ AssertEquals('Wrong MX preference', 10, fmx.preference);
+end;
+
+procedure TNetDbTest.TestDnsRRBufferPastEdgeMX;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart, oldstart: Word;
+ RRArr: TRRNameDataArray;
+ fmx: TDNSRR_MX;
+begin
+ BuildFakeResponseMX(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of MX records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+
+ // move the MX RR bytes to the end of the payload buffer. We omit the last
+ // 2 bytes of the MX to attempt to trick the code into reading past the buffer
+ // edge.
+ oldstart := RRArr[0].RDataSt;
+ RRArr[0].RDataSt := Length(qd.Payload) - (RRArr[0].RRMeta.RDLength - 2);
+ CopyBytesTo(qd.Payload, oldstart, RRArr[0].RDataSt,
+ (RRArr[0].RRMeta.RDLength-2));
+
+ AssertTrue('Got RR MX data.', DNSRRGetMX(RRArr[0], qd.Payload, fmx));
+ // stringfromlabel should drop the last label, so the result should be just
+ // missing the tld.
+ AssertEquals('Wrong MX hostname', 'mailer.'+FAKEDOMAIN,
+ fmx.exchange);
+ AssertEquals('Wrong MX preference', 10, fmx.preference);
+end;
+
+procedure TNetDbTest.TestDnsRRBufferEdgeSOA;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart, oldstart: Word;
+ RRArr: TRRNameDataArray;
+ soarec: TDNSRR_SOA;
+begin
+ BuildFakeResponseSOA(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of SOA records.', 1, qd.h.ancount);
+
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an SOA RR.',DNSQRY_SOA, RRarr[0].RRMeta.Atype);
+
+ // move the SOA RR bytes to the end of the payload buffer.
+ oldstart := RRArr[0].RDataSt;
+ RRArr[0].RDataSt := Length(qd.Payload) - RRArr[0].RRMeta.RDLength;
+ CopyBytesTo(qd.Payload, oldstart, RRArr[0].RDataSt, RRArr[0].RRMeta.RDLength);
+
+ AssertTrue('Did not get RR SOA data.', DNSRRGetSOA(RRArr[0], qd.Payload,
+ soarec));
+ AssertEquals('Wrong mname hostname', 'mn.'+FAKEFQDN,
+ soarec.mname);
+ AssertEquals('Wrong rname hostname', 'rn.'+FAKEFQDN,
+ soarec.rname);
+ AssertEquals('Wrong SOA serial', 76543210, soarec.serial);
+ AssertEquals('Wrong SOA refresh', 123, soarec.refresh);
+ AssertEquals('Wrong SOA retry', 456, soarec.retry);
+ AssertEquals('Wrong SOA expire', 789, soarec.expire);
+ AssertEquals('Wrong SOA min', 60, soarec.min);
+end;
+
+procedure TNetDbTest.TestDnsRRBufferPastEdgeSOA;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart, oldstart: Word;
+ RRArr: TRRNameDataArray;
+ soarec: TDNSRR_SOA;
+begin
+ BuildFakeResponseSOA(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of SOA records.', 1, qd.h.ancount);
+
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an SOA RR.',DNSQRY_SOA, RRarr[0].RRMeta.Atype);
+
+ // move the SOA RR bytes to the end of the payload buffer.
+ oldstart := RRArr[0].RDataSt;
+ RRArr[0].RDataSt := Length(qd.Payload) - (RRArr[0].RRMeta.RDLength-1);
+ CopyBytesTo(qd.Payload, oldstart, RRArr[0].RDataSt,
+ (RRArr[0].RRMeta.RDLength-1));
+
+ AssertFalse('Got RR SOA data.', DNSRRGetSOA(RRArr[0], qd.Payload,
+ soarec));
+end;
+
+procedure TNetDbTest.TestDnsRRBufferEdgeSRV;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart, oldstart: Word;
+ RRArr: TRRNameDataArray;
+ srvrec: TDNSRR_SRV;
+begin
+ BuildFakeResponseSRV(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of SRV records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an SRV RR.',DNSQRY_SRV, RRarr[0].RRMeta.Atype);
+
+ // move the SRV RR bytes to the end of the payload buffer.
+ oldstart := RRArr[0].RDataSt;
+ RRArr[0].RDataSt := Length(qd.Payload) - RRArr[0].RRMeta.RDLength;
+ CopyBytesTo(qd.Payload, oldstart, RRArr[0].RDataSt, RRArr[0].RRMeta.RDLength);
+
+ AssertTrue('Did not get RR SRV data.', DNSRRGetSRV(RRArr[0], qd.Payload,
+ srvrec));
+ AssertEquals('Wrong SRV priority', 22, srvrec.priority);
+ AssertEquals('Wrong SRV weight', 44, srvrec.weight);
+ AssertEquals('Wrong SRV port', 2201, srvrec.port);
+
+ AssertEquals('Wrong SRV hostname', '_this._that._other', srvrec.target);
+end;
+
+procedure TNetDbTest.TestDnsRRBufferPastEdgeSRV;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart, oldstart: Word;
+ RRArr: TRRNameDataArray;
+ srvrec: TDNSRR_SRV;
+begin
+ BuildFakeResponseSRV(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of SRV records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an SRV RR.',DNSQRY_SRV, RRarr[0].RRMeta.Atype);
+
+ // move the SRV RR bytes to the end of the payload buffer. ensure that
+ // we're one byte short to try and trick the code into reading past the
+ // end of the buffer.
+ oldstart := RRArr[0].RDataSt;
+ RRArr[0].RDataSt := Length(qd.Payload) - (RRArr[0].RRMeta.RDLength - 1);
+ CopyBytesTo(qd.Payload, oldstart, RRArr[0].RDataSt,
+ (RRArr[0].RRMeta.RDLength - 1));
+
+ AssertFalse('Got RR SRV data.', DNSRRGetSRV(RRArr[0], qd.Payload,
+ srvrec));
+end;
+
+procedure TNetDbTest.TestDnsRRBufferEdgeCNAME;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart, oldstart: Word;
+ RRArr: TRRNameDataArray;
+ s: TDNSDomainName;
+begin
+ BuildFakeResponseCNAME(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of CNAME records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an CNAME RR.',DNSQRY_CNAME, RRarr[0].RRMeta.Atype);
+
+ // move the cname to the end of the buffer.
+ oldstart := RRArr[0].RDataSt;
+ RRArr[0].RDataSt := Length(qd.Payload) - RRArr[0].RRMeta.RDLength;
+ CopyBytesTo(qd.Payload, oldstart, RRArr[0].RDataSt, RRArr[0].RRMeta.RDLength);
+
+ AssertTrue('Did not get RR CNAME data.', DNSRRGetCNAME(RRArr[0], qd.Payload, s));
+ AssertEquals('Wrong CNAME.', 'fakecname.'+FAKEFQDN, s);
+end;
+
+{
+Test retrieving a cname when the actual string is longer than rdlength says it
+is. The bytes in the payload buffer try to point past the end of the buffer.
+}
+procedure TNetDbTest.TestDnsRRBufferPastEdgeCNAME;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart, oldstart: Word;
+ RRArr: TRRNameDataArray;
+ s: TDNSDomainName;
+begin
+ BuildFakeResponseCNAME(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of CNAME records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an CNAME RR.',DNSQRY_CNAME, RRarr[0].RRMeta.Atype);
+
+ // move the cname to the end of the buffer. we drop two bytes off the end of
+ // the cname, because there's a 0 byte at the end of a label if not a ptr.
+ // now, the last label's size is greater than the number of bytes left in
+ // the buffer.
+ oldstart := RRArr[0].RDataSt;
+ RRArr[0].RDataSt := Length(qd.Payload) - (RRArr[0].RRMeta.RDLength-2);
+ CopyBytesTo(qd.Payload, oldstart, RRArr[0].RDataSt,
+ (RRArr[0].RRMeta.RDLength-2));
+
+ // lie about the rdlength too!
+ Dec(RRArr[0].RRMeta.RDLength,2);
+ AssertTrue('Did not get RR CNAME data.', DNSRRGetCNAME(RRArr[0], qd.Payload, s));
+ // last label will get removed, leaving just the domain part.
+ AssertEquals('Wrong CNAME.', 'fakecname.'+FAKEDOMAIN, s);
+end;
+
+{
+Test retrieving an NS RR when it's at the end of the payload buffer.
+}
+procedure TNetDbTest.TestDnsRRBufferEdgeNS;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart, oldstart: Word;
+ RRArr: TRRNameDataArray;
+ s: TDNSDomainName;
+begin
+ BuildFakeResponseNS(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of NS records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an NS RR.',DNSQRY_NS, RRarr[0].RRMeta.Atype);
+ AssertEquals('Wrong NS record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+
+ // move the ns to the end of the buffer.
+ oldstart := RRArr[0].RDataSt;
+ RRArr[0].RDataSt := Length(qd.Payload) - RRArr[0].RRMeta.RDLength;
+ CopyBytesTo(qd.Payload, oldstart, RRArr[0].RDataSt, RRArr[0].RRMeta.RDLength);
+
+ AssertTrue('Did not get RR NS data.', DNSRRGetNS(RRArr[0], qd.Payload, s));
+ AssertEquals('Wrong NS.', 'fakens.'+FAKEFQDN, s);
+end;
+
+procedure TNetDbTest.TestDnsRRBufferPastEdgeNS;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart, oldstart: Word;
+ RRArr: TRRNameDataArray;
+ s: TDNSDomainName;
+begin
+ BuildFakeResponseNS(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of NS records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an NS RR.',DNSQRY_NS, RRarr[0].RRMeta.Atype);
+
+ // move the ns to the end of the buffer. we drop two bytes off the end of
+ // the ns, because there's a 0 byte at the end of a label if not a ptr.
+ // now, the last label's size is greater than the number of bytes left in
+ // the buffer.
+ oldstart := RRArr[0].RDataSt;
+ RRArr[0].RDataSt := Length(qd.Payload) - (RRArr[0].RRMeta.RDLength-2);
+ CopyBytesTo(qd.Payload, oldstart, RRArr[0].RDataSt,
+ (RRArr[0].RRMeta.RDLength-2));
+
+ // lie about the rdlength too!
+ Dec(RRArr[0].RRMeta.RDLength,2);
+ AssertTrue('Did not get RR NS data.', DNSRRGetNS(RRArr[0], qd.Payload, s));
+ // last label will get removed, leaving just the domain part.
+ AssertEquals('Wrong NS.', 'fakens.'+FAKEDOMAIN, s);
+end;
+
+procedure TNetDbTest.TestDnsRRBufferEdgePTR;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart, oldstart: Word;
+ RRArr: TRRNameDataArray;
+ s: TDNSDomainName;
+begin
+ // the str passed in to this function doesn't really matter, but using
+ // a proper in-addr.arpa domain helps keep it clear what we're testing.
+ BuildFakeResponsePTR('0.5.0.127.in-addr.arpa', fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of PTR records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an PTR RR.',DNSQRY_PTR, RRarr[0].RRMeta.Atype);
+ AssertEquals('Wrong PTR record name for RR 0', '0.5.0.127.in-addr.arpa',
+ RRArr[0].RRName);
+
+ // move the ptr to the end of the buffer.
+ oldstart := RRArr[0].RDataSt;
+ RRArr[0].RDataSt := Length(qd.Payload) - RRArr[0].RRMeta.RDLength;
+ CopyBytesTo(qd.Payload, oldstart, RRArr[0].RDataSt, RRArr[0].RRMeta.RDLength);
+
+ AssertTrue('Did not get RR PTR data.', DNSRRGetPTR(RRArr[0], qd.Payload, s));
+ AssertEquals('Wrong PTR.', 'fakeptrans.'+FAKEFQDN, s);
+end;
+
+procedure TNetDbTest.TestDnsRRBufferPastEdgePTR;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart, oldstart: Word;
+ RRArr: TRRNameDataArray;
+ s: TDNSDomainName;
+begin
+ // the str passed in to this function doesn't really matter, but using
+ // a proper in-addr.arpa domain helps keep it clear what we're testing.
+ BuildFakeResponsePTR('0.5.0.127.in-addr.arpa', fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of PTR records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an PTR RR.',DNSQRY_PTR, RRarr[0].RRMeta.Atype);
+ AssertEquals('Wrong PTR record name for RR 0', '0.5.0.127.in-addr.arpa',
+ RRArr[0].RRName);
+
+ // move the ns to the end of the buffer. we drop two bytes off the end of
+ // the ns, because there's a 0 byte at the end of a label if not a ptr.
+ // now, the last label's size is greater than the number of bytes left in
+ // the buffer.
+ oldstart := RRArr[0].RDataSt;
+ RRArr[0].RDataSt := Length(qd.Payload) - (RRArr[0].RRMeta.RDLength-2);
+ CopyBytesTo(qd.Payload, oldstart, RRArr[0].RDataSt,
+ (RRArr[0].RRMeta.RDLength-2));
+
+ // lie about the rdlength too!
+ Dec(RRArr[0].RRMeta.RDLength,2);
+ AssertTrue('Did not get RR PTR data.', DNSRRGetPTR(RRArr[0], qd.Payload, s));
+ // last label will get removed, leaving just the domain part.
+ AssertEquals('Wrong PTR.', 'fakeptrans.'+FAKEDOMAIN, s);
+end;
+
+{
+Test reading a text record right at the edge of the payload buffer.
+}
+procedure TNetDbTest.TestDnsRRBufferEdgeTXT;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart,oldstart: Word;
+ RRArr: TRRNameDataArray;
+ s: AnsiString;
+begin
+ s := '';
+ BuildFakeResponseTXT(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of TXT records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not a TXT RR.',DNSQRY_TXT, RRarr[0].RRMeta.Atype);
+ AssertEquals('Wrong TXT record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+
+ // Move the text record to the end of the buffer
+ oldstart := RRArr[0].RDataSt;
+ RRArr[0].RDataSt := Length(qd.Payload) - RRArr[0].RRMeta.RDLength;
+ CopyBytesTo(qd.Payload, oldstart, RRArr[0].RDataSt, RRArr[0].RRMeta.RDLength);
+ AssertTrue('Did not get RR TXT data.', DNSRRGetText(RRArr[0], qd.Payload, s));
+ AssertEquals(
+ 'v=spf1 mx a:lists.'+FAKEFQDN+'Always look on the bright side of life!',
+ s);
+end;
+
+{
+Try reading a TXT record that points past the end of the payload buffer.
+}
+procedure TNetDbTest.TestDnsRRBufferPastEdgeTXT;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart,oldstart: Word;
+ RRArr: TRRNameDataArray;
+ s: AnsiString;
+begin
+ s := '';
+ BuildFakeResponseTXT(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of TXT records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not a TXT RR.',DNSQRY_TXT, RRarr[0].RRMeta.Atype);
+ AssertEquals('Wrong TXT record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+
+ // Move the text record to the end of the buffer, cutting off the last
+ // 2 bytes. this means the length byte for the second string will point
+ // past the end of the buffer.
+ oldstart := RRArr[0].RDataSt;
+ RRArr[0].RDataSt := Length(qd.Payload) - (RRArr[0].RRMeta.RDLength - 2);
+ CopyBytesTo(qd.Payload, oldstart, RRArr[0].RDataSt,
+ (RRArr[0].RRMeta.RDLength - 2));
+ AssertFalse('Did not get RR TXT data.',
+ DNSRRGetText(RRArr[0], qd.Payload, s));
+end;
+
+procedure TNetDbTest.TestDnsRRBufferEdgeTCPA;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ ip: THostAddr;
+begin
+ BuildFakeResponseA(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of A records.', 2, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+
+ // Change start position for RR[0] to end of buffer - 4
+ RRArr[0].RDataSt := Length(qd.Payload) - RRArr[0].RRMeta.RDLength;
+ qd.Payload[Length(qd.Payload)-1] := $AA; // sentinel marker we can look for
+ AssertTrue('Did not get RR A data.', DNSRRGetA(RRArr[0], qd.Payload, ip));
+ AssertEquals('Wrong ip for A.', '0.0.0.170', HostAddrToStr(ip));
+end;
+
+procedure TNetDbTest.TestDnsRRBufferPastEdgeTCPA;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ ip: THostAddr;
+begin
+ BuildFakeResponseA(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of A records.', 2, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+
+ // Change start position for RR[0] to end of buffer - 3
+ RRArr[0].RDataSt := Length(qd.Payload) - (RRArr[0].RRMeta.RDLength - 2);
+ AssertFalse('Got RR A data.', DNSRRGetA(RRArr[0], qd.Payload, ip));
+end;
+
+procedure TNetDbTest.TestDnsRRBufferEdgeTCPAAAA;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ ip: THostAddr6;
+begin
+ BuildFakeResponseAAAA(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of AAAA records.', 2, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ // Change start position for RR[0]
+ RRArr[0].RDataSt := Length(qd.Payload) - SizeOf(THostAddr6);
+ qd.Payload[Length(qd.Payload)-1] := $AA;
+ AssertTrue('Got RR AAAA data.', DNSRRGetAAAA(RRArr[0], qd.Payload, ip));
+ AssertEquals($AA, ip.u6_addr8[15]);
+end;
+
+procedure TNetDbTest.TestDNsRRBufferPastEdgeTCPAAAA;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+ ip: THostAddr6;
+begin
+ BuildFakeResponseAAAA(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of AAAA records.', 2, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ // Change start position for RR[0]. attempting to read 16 bytes
+ // from this position will pass the end of the buffer.
+ RRArr[0].RDataSt := Length(qd.Payload) - (SizeOf(THostAddr6)-1);
+ AssertFalse('Got RR AAAA data.', DNSRRGetAAAA(RRArr[0], qd.Payload, ip));
+end;
+
+procedure TNetDbTest.TestDnsRRBufferEdgeTCPMX;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart, oldstart: Word;
+ RRArr: TRRNameDataArray;
+ fmx: TDNSRR_MX;
+begin
+ BuildFakeResponseMX(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of MX records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+
+ // move the MX RR bytes to the end of the payload buffer.
+ oldstart := RRArr[0].RDataSt;
+ RRArr[0].RDataSt := Length(qd.Payload) - RRArr[0].RRMeta.RDLength;
+ CopyBytesTo(qd.Payload, oldstart, RRArr[0].RDataSt, RRArr[0].RRMeta.RDLength);
+
+ AssertTrue('Got RR MX data.', DNSRRGetMX(RRArr[0], qd.Payload, fmx));
+ AssertEquals('Wrong MX hostname', 'mailer.'+FAKEFQDN,
+ fmx.exchange);
+ AssertEquals('Wrong MX preference', 10, fmx.preference);
+end;
+
+procedure TNetDbTest.TestDnsRRBufferPastEdgeTCPMX;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart, oldstart: Word;
+ RRArr: TRRNameDataArray;
+ fmx: TDNSRR_MX;
+begin
+ BuildFakeResponseMX(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of MX records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+
+ // move the MX RR bytes to the end of the payload buffer. We omit the last
+ // 2 bytes of the MX to attempt to trick the code into reading past the buffer
+ // edge.
+ oldstart := RRArr[0].RDataSt;
+ RRArr[0].RDataSt := Length(qd.Payload) - (RRArr[0].RRMeta.RDLength - 2);
+ CopyBytesTo(qd.Payload, oldstart, RRArr[0].RDataSt,
+ (RRArr[0].RRMeta.RDLength-2));
+
+ AssertTrue('Got RR MX data.', DNSRRGetMX(RRArr[0], qd.Payload, fmx));
+ // stringfromlabel should drop the last label, so the result should be just
+ // missing the tld.
+ AssertEquals('Wrong MX hostname', 'mailer.'+FAKEDOMAIN,
+ fmx.exchange);
+ AssertEquals('Wrong MX preference', 10, fmx.preference);
+end;
+
+procedure TNetDbTest.TestDnsRRBufferEdgeTCPSOA;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart, oldstart: Word;
+ RRArr: TRRNameDataArray;
+ soarec: TDNSRR_SOA;
+begin
+ BuildFakeResponseSOA(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of SOA records.', 1, qd.h.ancount);
+
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an SOA RR.',DNSQRY_SOA, RRarr[0].RRMeta.Atype);
+
+ // move the SOA RR bytes to the end of the payload buffer.
+ oldstart := RRArr[0].RDataSt;
+ RRArr[0].RDataSt := Length(qd.Payload) - RRArr[0].RRMeta.RDLength;
+ CopyBytesTo(qd.Payload, oldstart, RRArr[0].RDataSt, RRArr[0].RRMeta.RDLength);
+
+ AssertTrue('Did not get RR SOA data.', DNSRRGetSOA(RRArr[0], qd.Payload,
+ soarec));
+ AssertEquals('Wrong mname hostname', 'mn.'+FAKEFQDN,
+ soarec.mname);
+ AssertEquals('Wrong rname hostname', 'rn.'+FAKEFQDN,
+ soarec.rname);
+ AssertEquals('Wrong SOA serial', 76543210, soarec.serial);
+ AssertEquals('Wrong SOA refresh', 123, soarec.refresh);
+ AssertEquals('Wrong SOA retry', 456, soarec.retry);
+ AssertEquals('Wrong SOA expire', 789, soarec.expire);
+ AssertEquals('Wrong SOA min', 60, soarec.min);
+end;
+
+procedure TNetDbTest.TestDnsRRBufferPastEdgeTCPSOA;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart, oldstart: Word;
+ RRArr: TRRNameDataArray;
+ soarec: TDNSRR_SOA;
+begin
+ BuildFakeResponseSOA(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of SOA records.', 1, qd.h.ancount);
+
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an SOA RR.',DNSQRY_SOA, RRarr[0].RRMeta.Atype);
+
+ // move the SOA RR bytes to the end of the payload buffer.
+ oldstart := RRArr[0].RDataSt;
+ RRArr[0].RDataSt := Length(qd.Payload) - (RRArr[0].RRMeta.RDLength-1);
+ CopyBytesTo(qd.Payload, oldstart, RRArr[0].RDataSt,
+ (RRArr[0].RRMeta.RDLength-1));
+
+ AssertFalse('Got RR SOA data.', DNSRRGetSOA(RRArr[0], qd.Payload,
+ soarec));
+end;
+
+procedure TNetDbTest.TestDnsRRBufferEdgeTCPSRV;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart, oldstart: Word;
+ RRArr: TRRNameDataArray;
+ srvrec: TDNSRR_SRV;
+begin
+ BuildFakeResponseSRV(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of SRV records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an SRV RR.',DNSQRY_SRV, RRarr[0].RRMeta.Atype);
+
+ // move the SRV RR bytes to the end of the payload buffer.
+ oldstart := RRArr[0].RDataSt;
+ RRArr[0].RDataSt := Length(qd.Payload) - RRArr[0].RRMeta.RDLength;
+ CopyBytesTo(qd.Payload, oldstart, RRArr[0].RDataSt, RRArr[0].RRMeta.RDLength);
+
+ AssertTrue('Did not get RR SRV data.', DNSRRGetSRV(RRArr[0], qd.Payload,
+ srvrec));
+ AssertEquals('Wrong SRV priority', 22, srvrec.priority);
+ AssertEquals('Wrong SRV weight', 44, srvrec.weight);
+ AssertEquals('Wrong SRV port', 2201, srvrec.port);
+
+ AssertEquals('Wrong SRV hostname', '_this._that._other', srvrec.target);
+end;
+
+procedure TNetDbTest.TestDnsRRBufferPastEdgeTCPSRV;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart, oldstart: Word;
+ RRArr: TRRNameDataArray;
+ srvrec: TDNSRR_SRV;
+begin
+ BuildFakeResponseSRV(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of SRV records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an SRV RR.',DNSQRY_SRV, RRarr[0].RRMeta.Atype);
+
+ // move the SRV RR bytes to the end of the payload buffer. ensure that
+ // we're one byte short to try and trick the code into reading past the
+ // end of the buffer.
+ oldstart := RRArr[0].RDataSt;
+ RRArr[0].RDataSt := Length(qd.Payload) - (RRArr[0].RRMeta.RDLength - 1);
+ CopyBytesTo(qd.Payload, oldstart, RRArr[0].RDataSt,
+ (RRArr[0].RRMeta.RDLength - 1));
+
+ AssertFalse('Got RR SRV data.', DNSRRGetSRV(RRArr[0], qd.Payload,
+ srvrec));
+end;
+
+procedure TNetDbTest.TestDnsRRBufferEdgeTCPCNAME;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart, oldstart: Word;
+ RRArr: TRRNameDataArray;
+ s: TDNSDomainName;
+begin
+ BuildFakeResponseCNAME(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of CNAME records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an CNAME RR.',DNSQRY_CNAME, RRarr[0].RRMeta.Atype);
+
+ // move the cname to the end of the buffer.
+ oldstart := RRArr[0].RDataSt;
+ RRArr[0].RDataSt := Length(qd.Payload) - RRArr[0].RRMeta.RDLength;
+ CopyBytesTo(qd.Payload, oldstart, RRArr[0].RDataSt, RRArr[0].RRMeta.RDLength);
+
+ AssertTrue('Did not get RR CNAME data.', DNSRRGetCNAME(RRArr[0], qd.Payload, s));
+ AssertEquals('Wrong CNAME.', 'fakecname.'+FAKEFQDN, s);
+end;
+
+procedure TNetDbTest.TestDnsRRBufferPastEdgeTCPCNAME;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart, oldstart: Word;
+ RRArr: TRRNameDataArray;
+ s: TDNSDomainName;
+begin
+ BuildFakeResponseCNAME(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of CNAME records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an CNAME RR.',DNSQRY_CNAME, RRarr[0].RRMeta.Atype);
+
+ // move the cname to the end of the buffer. we drop two bytes off the end of
+ // the cname, because there's a 0 byte at the end of a label if not a ptr.
+ // now, the last label's size is greater than the number of bytes left in
+ // the buffer.
+ oldstart := RRArr[0].RDataSt;
+ RRArr[0].RDataSt := Length(qd.Payload) - (RRArr[0].RRMeta.RDLength-2);
+ CopyBytesTo(qd.Payload, oldstart, RRArr[0].RDataSt,
+ (RRArr[0].RRMeta.RDLength-2));
+
+ // lie about the rdlength too!
+ Dec(RRArr[0].RRMeta.RDLength,2);
+ AssertTrue('Did not get RR CNAME data.', DNSRRGetCNAME(RRArr[0], qd.Payload, s));
+ // last label will get removed, leaving just the domain part.
+ AssertEquals('Wrong CNAME.', 'fakecname.'+FAKEDOMAIN, s);
+end;
+
+procedure TNetDbTest.TestDnsRRBufferEdgeTCPNS;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart, oldstart: Word;
+ RRArr: TRRNameDataArray;
+ s: TDNSDomainName;
+begin
+ BuildFakeResponseNS(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of NS records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an NS RR.',DNSQRY_NS, RRarr[0].RRMeta.Atype);
+ AssertEquals('Wrong NS record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+
+ // move the ns to the end of the buffer.
+ oldstart := RRArr[0].RDataSt;
+ RRArr[0].RDataSt := Length(qd.Payload) - RRArr[0].RRMeta.RDLength;
+ CopyBytesTo(qd.Payload, oldstart, RRArr[0].RDataSt, RRArr[0].RRMeta.RDLength);
+
+ AssertTrue('Did not get RR NS data.', DNSRRGetNS(RRArr[0], qd.Payload, s));
+ AssertEquals('Wrong NS.', 'fakens.'+FAKEFQDN, s);
+end;
+
+procedure TNetDbTest.TestDnsRRBufferPastEdgeTCPNS;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart, oldstart: Word;
+ RRArr: TRRNameDataArray;
+ s: TDNSDomainName;
+begin
+ BuildFakeResponseNS(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of NS records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an NS RR.',DNSQRY_NS, RRarr[0].RRMeta.Atype);
+
+ // move the ns to the end of the buffer. we drop two bytes off the end of
+ // the ns, because there's a 0 byte at the end of a label if not a ptr.
+ // now, the last label's size is greater than the number of bytes left in
+ // the buffer.
+ oldstart := RRArr[0].RDataSt;
+ RRArr[0].RDataSt := Length(qd.Payload) - (RRArr[0].RRMeta.RDLength-2);
+ CopyBytesTo(qd.Payload, oldstart, RRArr[0].RDataSt,
+ (RRArr[0].RRMeta.RDLength-2));
+
+ // lie about the rdlength too!
+ Dec(RRArr[0].RRMeta.RDLength,2);
+ AssertTrue('Did not get RR NS data.', DNSRRGetNS(RRArr[0], qd.Payload, s));
+ // last label will get removed, leaving just the domain part.
+ AssertEquals('Wrong NS.', 'fakens.'+FAKEDOMAIN, s);
+end;
+
+procedure TNetDbTest.TestDnsRRBufferEdgeTCPPTR;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart, oldstart: Word;
+ RRArr: TRRNameDataArray;
+ s: TDNSDomainName;
+begin
+ // the str passed in to this function doesn't really matter, but using
+ // a proper in-addr.arpa domain helps keep it clear what we're testing.
+ BuildFakeResponsePTR('0.5.0.127.in-addr.arpa', fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of PTR records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an PTR RR.',DNSQRY_PTR, RRarr[0].RRMeta.Atype);
+ AssertEquals('Wrong PTR record name for RR 0', '0.5.0.127.in-addr.arpa',
+ RRArr[0].RRName);
+
+ // move the ptr to the end of the buffer.
+ oldstart := RRArr[0].RDataSt;
+ RRArr[0].RDataSt := Length(qd.Payload) - RRArr[0].RRMeta.RDLength;
+ CopyBytesTo(qd.Payload, oldstart, RRArr[0].RDataSt, RRArr[0].RRMeta.RDLength);
+
+ AssertTrue('Did not get RR PTR data.', DNSRRGetPTR(RRArr[0], qd.Payload, s));
+ AssertEquals('Wrong PTR.', 'fakeptrans.'+FAKEFQDN, s);
+end;
+
+procedure TNetDbTest.TestDnsRRBufferPastEdgeTCPPTR;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart, oldstart: Word;
+ RRArr: TRRNameDataArray;
+ s: TDNSDomainName;
+begin
+ // the str passed in to this function doesn't really matter, but using
+ // a proper in-addr.arpa domain helps keep it clear what we're testing.
+ BuildFakeResponsePTR('0.5.0.127.in-addr.arpa', fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of PTR records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an PTR RR.',DNSQRY_PTR, RRarr[0].RRMeta.Atype);
+ AssertEquals('Wrong PTR record name for RR 0', '0.5.0.127.in-addr.arpa',
+ RRArr[0].RRName);
+
+ // move the ns to the end of the buffer. we drop two bytes off the end of
+ // the ns, because there's a 0 byte at the end of a label if not a ptr.
+ // now, the last label's size is greater than the number of bytes left in
+ // the buffer.
+ oldstart := RRArr[0].RDataSt;
+ RRArr[0].RDataSt := Length(qd.Payload) - (RRArr[0].RRMeta.RDLength-2);
+ CopyBytesTo(qd.Payload, oldstart, RRArr[0].RDataSt,
+ (RRArr[0].RRMeta.RDLength-2));
+
+ // lie about the rdlength too!
+ Dec(RRArr[0].RRMeta.RDLength,2);
+ AssertTrue('Did not get RR PTR data.', DNSRRGetPTR(RRArr[0], qd.Payload, s));
+ // last label will get removed, leaving just the domain part.
+ AssertEquals('Wrong PTR.', 'fakeptrans.'+FAKEDOMAIN, s);
+end;
+
+procedure TNetDbTest.TestDnsRRBufferEdgeTCPTXT;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart,oldstart: Word;
+ RRArr: TRRNameDataArray;
+ s: AnsiString;
+begin
+ s := '';
+ BuildFakeResponseTXT(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of TXT records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not a TXT RR.',DNSQRY_TXT, RRarr[0].RRMeta.Atype);
+ AssertEquals('Wrong TXT record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+
+ // Move the text record to the end of the buffer
+ oldstart := RRArr[0].RDataSt;
+ RRArr[0].RDataSt := Length(qd.Payload) - RRArr[0].RRMeta.RDLength;
+ CopyBytesTo(qd.Payload, oldstart, RRArr[0].RDataSt, RRArr[0].RRMeta.RDLength);
+ AssertTrue('Did not get RR TXT data.', DNSRRGetText(RRArr[0], qd.Payload, s));
+ AssertEquals(
+ 'v=spf1 mx a:lists.'+FAKEFQDN+'Always look on the bright side of life!',
+ s);
+end;
+
+procedure TNetDbTest.TestDnsRRBufferPastEdgeTCPTXT;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart,oldstart: Word;
+ RRArr: TRRNameDataArray;
+ s: AnsiString;
+begin
+ s := '';
+ BuildFakeResponseTXT(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of TXT records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not a TXT RR.',DNSQRY_TXT, RRarr[0].RRMeta.Atype);
+ AssertEquals('Wrong TXT record name for RR 0', FAKEFQDN,
+ RRArr[0].RRName);
+
+ // Move the text record to the end of the buffer, cutting off the last
+ // 2 bytes. this means the length byte for the second string will point
+ // past the end of the buffer.
+ oldstart := RRArr[0].RDataSt;
+ RRArr[0].RDataSt := Length(qd.Payload) - (RRArr[0].RRMeta.RDLength - 2);
+ CopyBytesTo(qd.Payload, oldstart, RRArr[0].RDataSt,
+ (RRArr[0].RRMeta.RDLength - 2));
+ AssertFalse('Did not get RR TXT data.',
+ DNSRRGetText(RRArr[0], qd.Payload, s));
+end;
+
+{
+Test that NextNameRR correctly reads an RR on the edge of the buffer.
+}
+procedure TNetDbTest.TestNextNameRREdgeA;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart: Word;
+ rrn: TRRNameData;
+ ip: THostAddr;
+ t: Cardinal;
+begin
+ BuildFakeResponseA(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+
+ // get an RR from its normal position. need this to calculate the length.
+ AssertTrue('NextNameRR should succeed.',
+ NextNameRR(qd.Payload, ansstart, rrn));
+
+ // calculate the size in bytes of the rr so we can copy it to the end
+ // of the payload buffer
+ t := (rrn.RDataSt + rrn.RRMeta.RDLength) - ansstart;
+ CopyBytesTo(qd.Payload,ansstart,Length(qd.Payload)-t, t);
+ AssertTrue('NextNameRR should succeed.',
+ NextNameRR(qd.Payload, Length(qd.Payload)-t, rrn));
+ AssertEquals(DNSQRY_A, rrn.RRMeta.Atype);
+ AssertEquals(300, rrn.RRMeta.TTL);
+ AssertTrue(DNSRRGetA(rrn, qd.Payload, ip));
+ AssertEquals('Wrong ip for A.', '127.0.0.1', HostAddrToStr(ip));
+end;
+
+{
+Try to trick NextNameRR into reading past the end of the payload buffer.
+}
+procedure TNetDbTest.TestNextNameRRPastEdgeA;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart: Word;
+ rrn: TRRNameData;
+ t: Cardinal;
+begin
+ BuildFakeResponseA(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+
+ // get an RR from its normal position. need this to calculate the length.
+ AssertTrue('NextNameRR should succeed.',
+ NextNameRR(qd.Payload, ansstart, rrn));
+
+ // calculate the size in bytes of the rr so we can copy it to the end
+ // of the payload buffer
+ t := (rrn.RDataSt + rrn.RRMeta.RDLength) - ansstart;
+ // copy the bytes, but leave off the last one. leave the rdlength unchanged.
+ CopyBytesTo(qd.Payload,ansstart,Length(qd.Payload)-(t-1), t-1);
+ AssertFalse('NextNameRR should fail.',
+ NextNameRR(qd.Payload, Length(qd.Payload)-(t-1), rrn));
+end;
+
+procedure TNetDbTest.TestNextNameRREdgeTCPA;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart: Word;
+ rrn: TRRNameData;
+ ip: THostAddr;
+ t: Cardinal;
+begin
+ BuildFakeResponseA(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+
+ // get an RR from its normal position. need this to calculate the length.
+ AssertTrue('NextNameRR should succeed.',
+ NextNameRR(qd.Payload, ansstart, rrn));
+
+ // calculate the size in bytes of the rr so we can copy it to the end
+ // of the payload buffer
+ t := (rrn.RDataSt + rrn.RRMeta.RDLength) - ansstart;
+ CopyBytesTo(qd.Payload,ansstart,Length(qd.Payload)-t, t);
+ AssertTrue('NextNameRR should succeed.',
+ NextNameRR(qd.Payload, Length(qd.Payload)-t, rrn));
+ AssertEquals(DNSQRY_A, rrn.RRMeta.Atype);
+ AssertEquals(300, rrn.RRMeta.TTL);
+ AssertTrue(DNSRRGetA(rrn, qd.Payload, ip));
+ AssertEquals('Wrong ip for A.', '127.0.0.1', HostAddrToStr(ip));
+end;
+
+procedure TNetDbTest.TestNextNameRRPastEdgeTCPA;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart: Word;
+ rrn: TRRNameData;
+ t: Cardinal;
+begin
+ BuildFakeResponseA(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+
+ // get an RR from its normal position. need this to calculate the length.
+ AssertTrue('NextNameRR should succeed.',
+ NextNameRR(qd.Payload, ansstart, rrn));
+
+ // calculate the size in bytes of the rr so we can copy it to the end
+ // of the payload buffer
+ t := (rrn.RDataSt + rrn.RRMeta.RDLength) - ansstart;
+ // copy the bytes, but leave off the last one. leave the rdlength unchanged.
+ CopyBytesTo(qd.Payload,ansstart,Length(qd.Payload)-(t-1), t-1);
+ AssertFalse('NextNameRR should fail.',
+ NextNameRR(qd.Payload, Length(qd.Payload)-(t-1), rrn));
+end;
+
+{
+Call GetRRrecords with a start position past the end of the buffer.
+}
+
+procedure TNetDbTest.TestGetRRrecordsInvalidStart;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+begin
+ BuildFakeResponseA(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := High(Word);
+ anslen := High(Word);
+ AssertEquals('Wrong number of A records.', 2, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, anslen);
+ AssertEquals(0, Length(RRArr));
+end;
+
+procedure TNetDbTest.TestGetRRrecordsInvalidStartTCP;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart: Word;
+ RRArr: TRRNameDataArray;
+begin
+ BuildFakeResponseA(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := High(Word);
+ anslen := High(Word);
+ AssertEquals('Wrong number of A records.', 2, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, anslen);
+ AssertEquals(0, Length(RRArr));
+end;
+
+procedure TNetDbTest.TestGetFixLenStrSimple;
+const
+ s = 'another fine mess';
+var
+ buf: TBuffer;
+ pl: TPayload;
+ tr: TTextArray;
+ offset: Cardinal;
+ res: ShortString;
+begin
+ tr[1] := s;
+ tr[2] := '';
+ tr[3] := '';
+ tr[4] := '';
+ tr[5] := '';
+ SetLength(buf, 1024);
+ offset := 0;
+ WriteTextRecAsRData(buf, offset, tr);
+ SetLength(buf, offset);
+ BufferToPayload(buf, pl);
+ // rdlength is word, so len byte for str is at offset 2 and str starts
+ // at offset 3.
+ GetFixlenStr(pl, 3, pl[2], res);
+ AssertEquals(s, res);
+end;
+
+procedure TNetDbTest.TestGetFixLenStrSimpleTCP;
+const
+ s = 'another fine mess';
+var
+ buf: TBuffer;
+ pl: TPayLoadTCP;
+ tr: TTextArray;
+ offset: Cardinal;
+ res: ShortString;
+begin
+ tr[1] := s;
+ tr[2] := '';
+ tr[3] := '';
+ tr[4] := '';
+ tr[5] := '';
+ SetLength(buf, 1024);
+ offset := 0;
+ WriteTextRecAsRData(buf, offset, tr);
+ SetLength(buf, offset);
+ BufferToPayload(buf, pl);
+ // rdlength is word, so len byte for str is at offset 2 and str starts
+ // at offset 3.
+ GetFixlenStr(pl, 3, pl[2], res);
+ AssertEquals(s, res);
+end;
+
+procedure TNetDbTest.TestGetFixLenStrSimpleAtEdge;
+const
+ s = 'another fine mess';
+var
+ buf: TBuffer;
+ pl: TPayload;
+ tr: TTextArray;
+ offset,n: Cardinal;
+ res: ShortString;
+begin
+ tr[1] := s;
+ tr[2] := '';
+ tr[3] := '';
+ tr[4] := '';
+ tr[5] := '';
+ SetLength(buf, Length(pl));
+ offset := Length(pl) - (Length(s)+3);
+ n := offset+2;
+ WriteTextRecAsRData(buf, offset, tr);
+ SetLength(buf, offset);
+ BufferToPayload(buf, pl);
+ GetFixlenStr(pl, n+1, pl[n], res);
+ AssertEquals(s, res);
+end;
+
+procedure TNetDbTest.TestGetFixLenStrSimpleTCPAtEdge;
+const
+ s = 'another fine mess';
+var
+ buf: TBuffer;
+ pl: TPayLoadTCP;
+ tr: TTextArray;
+ offset,n: Cardinal;
+ res: ShortString;
+begin
+ tr[1] := s;
+ tr[2] := '';
+ tr[3] := '';
+ tr[4] := '';
+ tr[5] := '';
+ SetLength(buf, Length(pl));
+ offset := Length(pl) - (Length(s)+3);
+ n := offset+2;
+ WriteTextRecAsRData(buf, offset, tr);
+ SetLength(buf, offset);
+ BufferToPayload(buf, pl);
+ GetFixlenStr(pl, n+1, pl[n], res);
+ AssertEquals(s, res);
+end;
+
+{
+Test GetFixLenStr where len would take string past edge of buffer.
+}
+procedure TNetDbTest.TestGetFixLenStrSimplePastEdge;
+var
+ pl: TPayLoadTCP;
+ res: ShortString;
+begin
+ pl[Length(pl) - 2] := 30;
+ pl[Length(pl) - 1] := Ord('a');
+ GetFixlenStr(pl, Length(pl)-1, pl[Length(pl)-2], res);
+ AssertEquals('', res);
+end;
+
+procedure TNetDbTest.TestGetFixLenStrSimpleTCPPastEdge;
+var
+ pl: TPayLoadTCP;
+ res: ShortString;
+begin
+ pl[Length(pl) - 2] := 30;
+ pl[Length(pl) - 1] := Ord('a');
+ GetFixlenStr(pl, Length(pl)-1, pl[Length(pl)-2], res);
+ AssertEquals('', res);
+end;
+
+{
+ read a label at the end of the buffer where the last byte is a count
+ greater than 0. this is to try and trick stringfromlabel into reading past
+ the end of the buffer.
+}
+procedure TNetDbTest.TestStringFromLabelCountAsLastByte;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryData;
+ anslen, ansstart, oldstart: Word;
+ RRArr: TRRNameDataArray;
+ s: TDNSDomainName;
+ startpos: Longint;
+begin
+ // we can use any of CNAME, NS or PTR because these RRs are just a single
+ // domain name or series of labels.
+ BuildFakeResponseNS(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of NS records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an NS RR.',DNSQRY_NS, RRarr[0].RRMeta.Atype);
+
+ // move the ns to the end of the buffer.
+ oldstart := RRArr[0].RDataSt;
+ RRArr[0].RDataSt := Length(qd.Payload) - RRArr[0].RRMeta.RDLength;
+ CopyBytesTo(qd.Payload, oldstart, RRArr[0].RDataSt, RRArr[0].RRMeta.RDLength);
+
+ // Set the last byte in the buffer to a high count
+ qd.Payload[Length(qd.Payload)-1] := 63; // must be less than 64
+
+ // need this var because stringfromlabel expects a longint that's a var type.
+ startpos := RRarr[0].RDataSt;
+ s := stringfromlabel(qd.Payload, startpos);
+ AssertEquals('fakens.'+FAKEFQDN, s);
+ AssertEquals(Length(qd.Payload), startpos);
+end;
+
+procedure TNetDbTest.TestStringFromLabelCountAsLastByteTCP;
+var
+ fakeresp: TFakeDNSResponse;
+ qd: TQueryDataLengthTCP;
+ anslen, ansstart, oldstart: Word;
+ RRArr: TRRNameDataArray;
+ s: TDNSDomainName;
+ startpos: Longint;
+begin
+ // we can use any of CNAME, NS or PTR because these RRs are just a single
+ // domain name or series of labels.
+ BuildFakeResponseNS(FAKEFQDN, fakeresp);
+ AssertTrue('Unable to convert fake dns response to querydata',
+ BuildQueryData(fakeresp, qd, anslen));
+ AssertTrue('CheckAnswer should return true.', CheckAnswer(qd.h,qd.h));
+ ansstart := SkipAnsQueries(qd, anslen);
+ AssertEquals('Wrong number of NS records.', 1, qd.h.ancount);
+ RRArr := GetRRrecords(qd.Payload, ansstart, qd.h.ancount);
+ AssertEquals('Wrong number of resource records.', 1, Length(RRArr));
+ AssertEquals('RR 0 is not an NS RR.',DNSQRY_NS, RRarr[0].RRMeta.Atype);
+
+ // move the ns to the end of the buffer.
+ oldstart := RRArr[0].RDataSt;
+ RRArr[0].RDataSt := Length(qd.Payload) - RRArr[0].RRMeta.RDLength;
+ CopyBytesTo(qd.Payload, oldstart, RRArr[0].RDataSt, RRArr[0].RRMeta.RDLength);
+
+ // Set the last byte in the buffer to a high count
+ qd.Payload[Length(qd.Payload)-1] := 63; // must be less than 64
+
+ // need this var because stringfromlabel expects a longint that's a var type.
+ startpos := RRarr[0].RDataSt;
+ s := stringfromlabel(qd.Payload, startpos);
+ AssertEquals('fakens.'+FAKEFQDN, s);
+ AssertEquals(Length(qd.Payload), startpos);
+end;
+
+procedure TNetDbTest.TestStringFromLabelCompress;
+var
+ buf: TBuffer;
+ stt: TDomainCompressionTable;
+ offset: Cardinal;
+ offset2: Longint;
+ pl: TPayload;
+ s: String;
+ dmbs: TDNSDomainByteStream;
+begin
+ SetLength(buf, 1024);
+ SetLength(stt,0);
+ offset := 0;
+ // initial str is uncompressed because compress table empty
+ dmbs := DomainNameToByteStream(FAKEFQDN, stt);
+ WriteDNSDomainByteStreamToBuffer(buf, offset, dmbs);
+ offset2 := offset;
+ // write same domain, this time we get compression.
+ dmbs := DomainNameToByteStream(FAKEFQDN, stt);
+ WriteDNSDomainByteStreamToBuffer(buf, offset, dmbs);
+ BufferToPayload(buf,pl);
+ s := stringfromlabel(pl, offset2);
+ AssertEquals(FAKEFQDN,s);
+end;
+
+procedure TNetDbTest.TestStringFromLabelCompressTCP;
+var
+ buf: TBuffer;
+ stt: TDomainCompressionTable;
+ offset: Cardinal;
+ offset2: Longint;
+ pl: TPayLoadTCP;
+ s: String;
+ dmbs: TDNSDomainByteStream;
+begin
+ SetLength(buf, 1024);
+ SetLength(stt,0);
+ offset := 0;
+ // initial str is uncompressed because compress table empty
+ dmbs := DomainNameToByteStream(FAKEFQDN, stt);
+ WriteDNSDomainByteStreamToBuffer(buf, offset, dmbs);
+ offset2 := offset;
+ // write same domain, this time we get compression.
+ dmbs := DomainNameToByteStream(FAKEFQDN, stt);
+ WriteDNSDomainByteStreamToBuffer(buf, offset, dmbs);
+ BufferToPayload(buf,pl);
+ s := stringfromlabel(pl, offset2);
+ AssertEquals(FAKEFQDN,s);
+end;
+
+procedure TNetDbTest.TestStringFromLabelCompressWithUncompressedLabel;
+var
+ buf: TBuffer;
+ dmbs: TDNSDomainByteStream;
+ offset: Cardinal;
+ so: Longint;
+ stt: TDomainCompressionTable;
+ len: Word;
+ pl: TPayload;
+ s: String;
+begin
+ SetLength(buf, 1024);
+ SetLength(stt,0);
+ // compress table empty so no compression here.
+ dmbs := DomainNameToByteStream(FAKEFQDN, stt);
+ offset := 0;
+ WriteDNSDomainByteStreamToBuffer(buf, offset, dmbs);
+
+ so := offset;
+ // should get compression on FAKEFQDN but label "foo" is written as full label.
+ dmbs := DomainNameToByteStream('foo.' + FAKEFQDN, stt);
+ len := CalcRdLength(dmbs);
+ // len is 4 for 'foo' (including its length byte) and 2 for the pointer.
+ AssertEquals(6, len);
+ WriteDNSDomainByteStreamToBuffer(buf, offset, dmbs);
+ BufferToPayload(buf,pl);
+ s := stringfromlabel(pl, so);
+ AssertEquals('foo.'+FAKEFQDN,s);
+end;
+
+procedure TNetDbTest.TestStringFromLabelCompressWithUncompressedLabelTCP;
+var
+ buf: TBuffer;
+ dmbs: TDNSDomainByteStream;
+ offset: Cardinal;
+ so: Longint;
+ stt: TDomainCompressionTable;
+ len: Word;
+ pl: TPayLoadTCP;
+ s: String;
+begin
+ SetLength(buf, 1024);
+ SetLength(stt,0);
+ // compress table empty so no compression here.
+ dmbs := DomainNameToByteStream(FAKEFQDN, stt);
+ offset := 0;
+ WriteDNSDomainByteStreamToBuffer(buf, offset, dmbs);
+
+ so := offset;
+ // should get compression on FAKEFQDN but label "foo" is written as full label.
+ dmbs := DomainNameToByteStream('foo.' + FAKEFQDN, stt);
+ len := CalcRdLength(dmbs);
+ // len is 4 for 'foo' (including its length byte) and 2 for the pointer.
+ AssertEquals(6, len);
+ WriteDNSDomainByteStreamToBuffer(buf, offset, dmbs);
+ BufferToPayload(buf,pl);
+ s := stringfromlabel(pl, so);
+ AssertEquals('foo.'+FAKEFQDN,s);
+end;
+
+{
+Test stringfromlabel with a compressed label at the end of the buffer.
+}
+procedure TNetDbTest.TestStringFromLabelCompressEndBuffer;
+var
+ buf: TBuffer;
+ stt: TDomainCompressionTable;
+ offset: Cardinal;
+ offset2: Longint;
+ pl: TPayload;
+ s: String;
+ dmbs: TDNSDomainByteStream;
+begin
+ SetLength(buf, 1024);
+ SetLength(stt,0);
+ offset := 0;
+
+ // initial str is uncompressed because compress table empty
+ dmbs := DomainNameToByteStream(FAKEFQDN, stt);
+ WriteDNSDomainByteStreamToBuffer(buf, offset, dmbs);
+ offset2 := offset;
+ // write same domain, this time we get compression.
+ dmbs := DomainNameToByteStream(FAKEFQDN, stt);
+
+ // write the pointer at the end of the payload buffer
+ offset := Length(pl) - 2;
+ WriteDNSDomainByteStreamToBuffer(buf, offset, dmbs);
+ BufferToPayload(buf,pl);
+
+ // read back the label.
+ offset2 := Length(pl) - 2;
+ s := stringfromlabel(pl, offset2);
+ AssertEquals(FAKEFQDN,s);
+end;
+
+procedure TNetDbTest.TestStringFromLabelCompressEndBufferTCP;
+var
+ buf: TBuffer;
+ stt: TDomainCompressionTable;
+ offset: Cardinal;
+ offset2: Longint;
+ pl: TPayLoadTCP;
+ s: String;
+ dmbs: TDNSDomainByteStream;
+begin
+ SetLength(buf, Length(pl));
+ SetLength(stt,0);
+ offset := 0;
+
+ // initial str is uncompressed because compress table empty
+ dmbs := DomainNameToByteStream(FAKEFQDN, stt);
+ WriteDNSDomainByteStreamToBuffer(buf, offset, dmbs);
+ offset2 := offset;
+ // write same domain, this time we get compression.
+ dmbs := DomainNameToByteStream(FAKEFQDN, stt);
+
+ // write the pointer at the end of the payload buffer
+ offset := Length(pl) - 2;
+ WriteDNSDomainByteStreamToBuffer(buf, offset, dmbs);
+ BufferToPayload(buf,pl);
+
+ // read back the label.
+ offset2 := Length(pl) - 2;
+ s := stringfromlabel(pl, offset2);
+ AssertEquals(FAKEFQDN,s);
+end;
+
+procedure TNetDbTest.TestStringFromLabelCompressSplit;
+var
+ pl: TPayload;
+ s: String;
+ offset: Longint;
+begin
+ // fill the buffer with 'A' so that we'll know if stringfromlabel read any
+ // of it.
+ FillByte(pl, Length(pl), 65);
+ offset := Length(pl) - 1;
+ pl[offset] := 192;
+ s := stringfromlabel(pl, offset);
+ AssertEquals('', s);
+end;
+
+procedure TNetDbTest.TestStringFromLabelCompressSplitTCP;
+var
+ pl: TPayLoadTCP;
+ s: String;
+ offset: Longint;
+begin
+ // fill the buffer with 'A' so that we'll know if stringfromlabel read any
+ // of it.
+ FillByte(pl, Length(pl), 65);
+ offset := Length(pl) - 1;
+ pl[offset] := 192;
+ s := stringfromlabel(pl, offset);
+ AssertEquals('', s);
+end;
+
+procedure TNetDbTest.TestStringFromLabelCompressPtrFwd;
+var
+ pl: TPayload;
+ s: String;
+ offset: Longint;
+ ptr: TDNSDomainPointer;
+begin
+ FillByte(pl, Length(pl), 0);
+ Move('foo', pl[21], 3);
+ pl[20] := 3;
+
+ ptr := GetDnsDomainPointer(32); // offset 20 + 12 for the header
+ offset := 0;
+ pl[offset] := ptr.b1;
+ pl[offset+1] := ptr.b2;
+ s := stringfromlabel(pl, offset);
+ AssertEquals('', s);
+end;
+
+procedure TNetDbTest.TestStringFromLabelCompressPtrFwdTCP;
+var
+ pl: TPayLoadTCP;
+ s: String;
+ offset: Longint;
+ ptr: TDNSDomainPointer;
+begin
+ FillByte(pl, Length(pl), 0);
+ Move('foo', pl[21], 3);
+ pl[20] := 3;
+
+ ptr := GetDnsDomainPointer(32); // offset 20 + 12 for the header
+ offset := 0;
+ pl[offset] := ptr.b1;
+ pl[offset+1] := ptr.b2;
+ s := stringfromlabel(pl, offset);
+ AssertEquals('', s);
+end;
+
+procedure TNetDbTest.TestStringFromLabelCompressAllPtrStart;
+var
+ pl: TPayload;
+ s: String;
+ offset: Longint;
+begin
+ FillByte(pl, Length(pl), 192);
+ offset := 0;
+ s := stringfromlabel(pl, offset);
+ AssertEquals('', s);
+end;
+
+procedure TNetDbTest.TestStringFromLabelCompressAllPtrStartTCP;
+var
+ pl: TPayLoadTCP;
+ s: String;
+ offset: Longint;
+begin
+ FillByte(pl, Length(pl), 192);
+ offset := 0;
+ s := stringfromlabel(pl, offset);
+ AssertEquals('', s);
+end;
+
+{
+Test what happens when pointer is 0.
+}
+procedure TNetDbTest.TestStringFromLabelCompressedZero;
+var
+ pl: TPayLoad;
+ s: String;
+ offset: Longint;
+ ptr: TDNSDomainPointer;
+begin
+ FillByte(pl, Length(pl), 0);
+ pl[0] := 1;
+ pl[1] := Ord('a');
+ ptr := GetDnsDomainPointer(0);
+ offset := 5;
+ pl[offset] := ptr.b1;
+ pl[offset+1] := ptr.b2;
+
+ s := stringfromlabel(pl, offset);
+ AssertEquals('', s);
+end;
+
+{
+Test what happens when pointer is 0.
+}
+procedure TNetDbTest.TestStringFromLabelCompressedZeroTCP;
+var
+ pl: TPayLoadTCP;
+ s: String;
+ offset: Longint;
+ ptr: TDNSDomainPointer;
+begin
+ FillByte(pl, Length(pl), 0);
+ pl[0] := 1;
+ pl[1] := Ord('a');
+ ptr := GetDnsDomainPointer(0);
+ offset := 5;
+ pl[offset] := ptr.b1;
+ pl[offset+1] := ptr.b2;
+
+ s := stringfromlabel(pl, offset);
+ AssertEquals('', s);
+end;
+
+procedure TNetDbTest.TestStringFromLabelInfiniteLoop;
+var
+ buf: TBuffer;
+ stt: TDomainCompressionTable;
+ offset: Cardinal;
+ offset2: Longint;
+ pl: TPayload;
+ s: String;
+ dmbs: TDNSDomainByteStream;
+ ptr: TDNSDomainPointer;
+begin
+ SetLength(buf, 1024);
+ SetLength(stt,0);
+ offset := 0;
+ // initial str is uncompressed because compress table empty
+ dmbs := DomainNameToByteStream(FAKEFQDN, stt);
+ WriteDNSDomainByteStreamToBuffer(buf, offset, dmbs);
+ ptr := GetDnsDomainPointer(12);
+
+ // offset now points to 0 byte at end of label. We're overwriting that
+ // 0 so that stringfromlabel will be tricked into a loop.
+ Dec(offset);
+ Move(ptr.ba, buf[offset], 2);
+
+ BufferToPayload(buf,pl);
+ offset2 := 0;
+ s := stringfromlabel(pl, offset2);
+ // if stringfromlabel returns at all then the test passed.
+end;
+
+procedure TNetDbTest.TestStringFromLabelInfiniteLoopTCP;
+var
+ buf: TBuffer;
+ stt: TDomainCompressionTable;
+ offset: Cardinal;
+ offset2: Longint;
+ pl: TPayLoadTCP;
+ s: String;
+ dmbs: TDNSDomainByteStream;
+ ptr: TDNSDomainPointer;
+begin
+ SetLength(buf, 1024);
+ SetLength(stt,0);
+ offset := 0;
+ // initial str is uncompressed because compress table empty
+ dmbs := DomainNameToByteStream(FAKEFQDN, stt);
+ WriteDNSDomainByteStreamToBuffer(buf, offset, dmbs);
+ ptr := GetDnsDomainPointer(12);
+
+ // offset now points to 0 byte at end of label. We're overwriting that
+ // 0 so that stringfromlabel will be tricked into a loop.
+ Dec(offset);
+ Move(ptr.ba, buf[offset], 2);
+
+ BufferToPayload(buf,pl);
+ offset2 := 0;
+ s := stringfromlabel(pl, offset2);
+ // if stringfromlabel returns at all then the test passed.
+end;
+
+procedure TNetDbTest.TestCompressShortDomain;
+const
+ shortdomain = 'a.b';
+var
+ buf: TBuffer;
+ stt: TDomainCompressionTable;
+ offset: Cardinal;
+ offset2: Longint;
+ pl: TPayload;
+ s: String;
+ dmbs: TDNSDomainByteStream;
+begin
+ SetLength(buf, 1024);
+ SetLength(stt,0);
+ offset := 0;
+ // initial str is uncompressed because compress table empty
+ dmbs := DomainNameToByteStream(shortdomain, stt);
+ WriteDNSDomainByteStreamToBuffer(buf, offset, dmbs);
+ offset2 := offset;
+ // second str is compressed
+ dmbs := DomainNameToByteStream(shortdomain, stt);
+ WriteDNSDomainByteStreamToBuffer(buf, offset, dmbs);
+
+ BufferToPayload(buf,pl);
+ s := stringfromlabel(pl, offset2);
+ AssertEquals(shortdomain, s);
+end;
+
+procedure TNetDbTest.TestCompressShortDomainTCP;
+const
+ shortdomain = 'a.b';
+var
+ buf: TBuffer;
+ stt: TDomainCompressionTable;
+ offset: Cardinal;
+ offset2: Longint;
+ pl: TPayLoadTCP;
+ s: String;
+ dmbs: TDNSDomainByteStream;
+begin
+ SetLength(buf, 1024);
+ SetLength(stt,0);
+ offset := 0;
+ // initial str is uncompressed because compress table empty
+ dmbs := DomainNameToByteStream(shortdomain, stt);
+ WriteDNSDomainByteStreamToBuffer(buf, offset, dmbs);
+ offset2 := offset;
+ // second str is compressed
+ dmbs := DomainNameToByteStream(shortdomain, stt);
+ WriteDNSDomainByteStreamToBuffer(buf, offset, dmbs);
+
+ BufferToPayload(buf,pl);
+ s := stringfromlabel(pl, offset2);
+ AssertEquals(shortdomain, s);
+end;
+
+procedure TNetDbTest.SetUp;
+begin
+ tsl := TStringList.Create;
+end;
+
+procedure TNetDbTest.TearDown;
+begin
+ tsl.Free;
+end;
+
+procedure TNetDbTest.CopyBytesTo(var buf: TPayLoad; startidx, destidx,
+ count: Word);
+begin
+ // no tests for overlapping source and dest.
+ if ((startidx+count) > Length(buf)) or ((destidx+count) > Length(buf)) then
+ exit;
+ Move(buf[startidx], buf[destidx], count);
+end;
+
+procedure TNetDbTest.CopyBytesTo(var buf: TPayLoadTCP; startidx, destidx,
+ count: Word);
+begin
+ // no tests for overlapping source and dest.
+ if ((startidx+count) > Length(buf)) or ((destidx+count) > Length(buf)) then
+ exit;
+ Move(buf[startidx], buf[destidx], count);
+end;
+
+function TNetDbTest.WriteNumToBuffer(var buf: TBuffer; var offset: Cardinal;
+ val: Word): Word;
+begin
+ Result := 0;
+ if (offset + SizeOf(val)) > Length(buf) then exit;
+ Move(HToNs(val), buf[offset], SizeOf(val));
+ Inc(offset, SizeOf(val));
+ Result := SizeOf(val);
+end;
+
+function TNetDbTest.WriteNumToBuffer(var buf: TBuffer; var offset: Cardinal;
+ val: Cardinal): Word;
+begin
+ Result := 0;
+ if (offset + SizeOf(val)) > Length(buf) then exit;
+ Move(HToNl(val), buf[offset], SizeOf(val));
+ Inc(offset, SizeOf(val));
+ Result := SizeOf(val);
+end;
+
+{
+Write a number to the buffer without converting it to network byte order.
+}
+function TNetDbTest.WriteNumToBufferN(var buf: TBuffer; var offset: Cardinal;
+ val: Word): Word;
+begin
+ Result := 0;
+ if (offset + SizeOf(val)) > Length(buf) then exit;
+ Move(val, buf[offset], SizeOf(val));
+ Inc(offset, SizeOf(val));
+ Result := SizeOf(val);
+end;
+
+{
+Write a number to the buffer without converting it to network byte order.
+}
+function TNetDbTest.WriteNumToBufferN(var buf: TBuffer; var offset: Cardinal;
+ val: Cardinal): Word;
+begin
+ Result := 0;
+ if (offset + SizeOf(val)) > Length(buf) then exit;
+ Move(val, buf[offset], SizeOf(val));
+ Inc(offset, SizeOf(val));
+ Result := SizeOf(val);
+end;
+
+{
+Write an RR to the byte buffer. No compression of domain names will occur.
+}
+function TNetDbTest.WriteRRToBuffer(var buf: TBuffer; var offset: Cardinal;
+ rr: TFakeRR): Word;
+var
+ s,etw: Word;
+ dmbs: TDNSDomainByteStream;
+ res: TRDataWriteRes;
+begin
+ etw := 0;
+ s := offset;
+ // write the RR Name
+ dmbs := DomainNameToByteStream(rr.RRName);
+ etw := CalcRdLength(dmbs);
+ if WriteDNSDomainByteStreamToBuffer(buf, offset, dmbs) < etw
+ then
+ Fail('Cannot write RR name to buffer at offset '+ inttostr(offset));
+
+ if (offset + SizeOf(rr.Atype) + SizeOf(rr.AClass) + SizeOf(rr.TTL)) >
+ Length(buf)
+ then
+ Fail('Not enough space to add RR type,class,ttl at offset '+ inttostr(offset));
+
+ // Write the RR type, class and TTL.
+ WriteNumToBuffer(buf, offset,rr.Atype);
+ WriteNumToBuffer(buf, offset, rr.AClass);
+ WriteNumToBuffer(buf, offset, rr.TTL);
+
+ // now the RR data, which is type specific. Each type-specific method
+ // also writes the RDLength word, so we have to account for 2 additional
+ // bytes.
+ case rr.Atype of
+ DNSQRY_A:
+ res := WriteAasRData(buf, offset, rr.ip);
+ DNSQRY_AAAA:
+ res := WriteAAAAasRData(buf, offset, rr.ip6);
+ DNSQRY_SOA:
+ res := WriteSOAasRData(buf, offset, rr.fsoa);
+ DNSQRY_MX:
+ res := WriteMXAsRData(buf, offset, rr.fmx);
+ DNSQRY_NS:
+ begin
+ dmbs := DomainNameToByteStream(rr.nsh);
+ res := WriteDomainAsRdata(buf,offset,dmbs);
+ end;
+ DNSQRY_PTR:
+ begin
+ dmbs := DomainNameToByteStream(rr.nsh);
+ res := WriteDomainAsRdata(buf,offset,dmbs);
+ end;
+ DNSQRY_CNAME:
+ begin
+ dmbs := DomainNameToByteStream(rr.cn);
+ res := WriteDomainAsRdata(buf,offset,dmbs);
+ end;
+ DNSQRY_TXT:
+ res := WriteTextRecAsRData(buf, offset, rr.txtarr);
+ DNSQRY_SRV:
+ res := WriteSRVasRData(buf, offset, rr.fsrv);
+ else
+ Fail('Called to handle RR type '+inttostr(rr.Atype)+
+ ' but no code to handle it.');
+ end;
+
+ if res.bw < res.etw then
+ Fail('Unable to write RR of type ' +inttostr(RR.Atype) +
+ ', name "' + rr.RRName + '" to buffer at offset '+inttostr(offset)+
+ '. Wrote '+inttostr(res.bw)+' bytes, expected to write '+
+ inttostr(res.etw)+' bytes.');
+
+ Result := offset - s;
+end;
+
+{
+Write an RR to the output buffer, with compression of domain names turned on.
+}
+function TNetDbTest.WriteRRToBuffer(var buf: TBuffer; var offset: Cardinal;
+ rr: TFakeRR; var ctbl: TDomainCompressionTable): Word;
+var
+ s, etw: Word;
+ dmbs: TDNSDomainByteStream;
+ res: TRDataWriteRes;
+begin
+ etw := 0;
+ s := offset;
+ // write the RR Name
+ dmbs := DomainNameToByteStream(rr.RRName, ctbl);
+ etw := CalcRdLength(dmbs);
+ if WriteDNSDomainByteStreamToBuffer(buf, offset, dmbs) < etw
+ then
+ Fail('Cannot write RR name to buffer at offset '+ inttostr(offset));
+
+ if (offset + SizeOf(rr.Atype) + SizeOf(rr.AClass) + SizeOf(rr.TTL)) >
+ Length(buf)
+ then
+ Fail('Not enough space to add RR type,class,ttl at offset '+ inttostr(offset));
+
+ // Write the RR type, class and TTL.
+ WriteNumToBuffer(buf, offset,rr.Atype);
+ WriteNumToBuffer(buf, offset, rr.AClass);
+ WriteNumToBuffer(buf, offset, rr.TTL);
+
+ // now the RR data, which is type specific. Each type-specific method
+ // also writes the RDLength word, so we have to account for 2 additional
+ // bytes.
+ case rr.Atype of
+ DNSQRY_A:
+ begin
+ res := WriteAasRData(buf, offset, rr.ip);
+ end;
+ DNSQRY_AAAA:
+ begin
+ res := WriteAAAAasRData(buf, offset, rr.ip6);
+ end;
+ DNSQRY_SOA:
+ begin
+ res := WriteSOAasRData(buf, offset, rr.fsoa);
+ end;
+ DNSQRY_MX:
+ begin
+ res := WriteMXAsRData(buf, offset, rr.fmx, ctbl);
+ end;
+ DNSQRY_NS:
+ begin
+ dmbs := DomainNameToByteStream(rr.nsh, ctbl);
+ res := WriteDomainAsRdata(buf,offset,dmbs);
+ end;
+ DNSQRY_PTR:
+ begin
+ dmbs := DomainNameToByteStream(rr.nsh, ctbl);
+ res := WriteDomainAsRdata(buf,offset,dmbs);
+ end;
+ DNSQRY_CNAME:
+ begin
+ dmbs := DomainNameToByteStream(rr.cn, ctbl);
+ res := WriteDomainAsRdata(buf,offset,dmbs);
+ end;
+ DNSQRY_TXT:
+ begin
+ res := WriteTextRecAsRData(buf, offset, rr.txtarr);
+ end;
+ DNSQRY_SRV:
+ begin
+ res := WriteSRVasRData(buf, offset, rr.fsrv);
+ end;
+ else
+ Fail('Called to handle RR type '+inttostr(rr.Atype)+
+ ' but no code to handle it.');
+ end;
+
+ if res.bw < res.etw then
+ Fail('Unable to write RR of type ' +inttostr(RR.Atype) +
+ ', name "' + rr.RRName + '" to buffer at offset '+inttostr(offset)+
+ '. Wrote '+inttostr(res.bw)+' bytes, expected to write '+
+ inttostr(res.etw)+' bytes.');
+
+ Result := offset - s;
+end;
+
+{
+Turn a fake DNS response into a payload buffer. This is a byte buffer minus the
+DNS header. That is, the buffer begins with the question part of the response,
+after which comes the RRs of the answers, authority, and additional sections.
+}
+function TNetDbTest.FakeDNSResponseToByteBuffer(fdr: TFakeDNSResponse; out
+ buf: TBuffer; compress: Boolean): Cardinal;
+var
+ offset: Cardinal;
+ rr: TFakeRR;
+ dbs: TDNSDomainByteStream;
+begin
+ // plenty of room for our test responses. could precalculate this, but there's
+ // no benefit. The return value of this function is the length of the
+ // DNS reply, which we get for free since we have to track our offset into
+ // the buffer as we write it.
+ SetLength(buf, 2048);
+ offset := 0;
+
+ if compress then
+ dbs := DomainNameToByteStream(fdr.qry.nm,fdr.strtable)
+ else
+ dbs := DomainNameToByteStream(fdr.qry.nm);
+
+ // The question section consists of the dns query name, the qtype and
+ // qclass.
+ if WriteDNSDomainByteStreamToBuffer(buf, offset, dbs) < CalcRdLength(dbs)
+ then
+ Fail('Cannot write name to buffer at offset '+ inttostr(offset));
+
+ WriteNumToBuffer(buf, offset, fdr.qry.qtype);
+ WriteNumToBuffer(buf, offset, fdr.qry.qclass);
+
+ // Now the answer sections.
+ for rr in fdr.answers do
+ if compress then
+ WriteRRToBuffer(buf, offset, rr, fdr.strtable)
+ else
+ WriteRRToBuffer(buf, offset, rr);
+ for rr in fdr.authority do
+ if compress then
+ WriteRRToBuffer(buf, offset, rr, fdr.strtable)
+ else
+ WriteRRToBuffer(buf, offset, rr);
+ for rr in fdr.additional do
+ if compress then
+ WriteRRToBuffer(buf, offset, rr, fdr.strtable)
+ else
+ WriteRRToBuffer(buf, offset, rr);
+
+ SetLength(buf, offset);
+ Result := offset;
+end;
+
+{
+Generate a TPayload buffer, a fixed-length array of byte, from the TBuffer
+type, which is a variable-length array of byte.
+}
+function TNetDbTest.BufferToPayload(const buf: TBuffer;
+ out pl: TPayload): Boolean;
+begin
+ Result := False;
+ FillChar(pl,Length(pl),0);
+ Move(buf[0], pl[0], Min(Length(pl),Length(buf)));
+ Result := True;
+end;
+
+function TNetDbTest.BufferToPayload(const buf: TBuffer;
+ out pl: TPayLoadTCP): Boolean;
+begin
+ Result := False;
+ FillChar(pl,Length(pl),0);
+ Move(buf[0], pl[0], Min(Length(pl),Length(buf)));
+ Result := True;
+end;
+
+function TNetDbTest.BuildQueryData(fdr: TFakeDNSResponse; out qd: TQueryData;
+ out qlen: Word; Compress: Boolean = False): Boolean;
+var
+ buf: TBuffer;
+begin
+ qlen := FakeDNSResponseToByteBuffer(fdr, buf, Compress);
+ qd.h.ancount := HToNs(fdr.hdr.ancount);
+ qd.h.arcount := HToNs(fdr.hdr.arcount);
+ qd.h.nscount := HToNs(fdr.hdr.nscount);
+ qd.h.qdcount := HToNs(fdr.hdr.qdcount);
+ qd.h.flags1 := fdr.hdr.flags1;
+ qd.h.flags2 := fdr.hdr.flags2;
+ qd.h.id[0] := fdr.hdr.id[0];
+ qd.h.id[1] := fdr.hdr.id[1];
+ Result := BufferToPayload(buf, qd.Payload);
+end;
+
+function TNetDbTest.BuildQueryData(fdr: TFakeDNSResponse; out
+ qd: TQueryDataLengthTCP; out qlen: Word; Compress: Boolean = False): Boolean;
+var
+ buf: TBuffer;
+begin
+ qlen := FakeDNSResponseToByteBuffer(fdr, buf, Compress);
+ qd.h.ancount := HToNs(fdr.hdr.ancount);
+ qd.h.arcount := HToNs(fdr.hdr.arcount);
+ qd.h.nscount := HToNs(fdr.hdr.nscount);
+ qd.h.qdcount := HToNs(fdr.hdr.qdcount);
+ qd.h.flags1 := fdr.hdr.flags1;
+ qd.h.flags2 := fdr.hdr.flags2;
+ qd.h.id[0] := fdr.hdr.id[0];
+ qd.h.id[1] := fdr.hdr.id[1];
+ Result := BufferToPayload(buf, qd.Payload);
+end;
+
+{
+Create a deliberately invalid DNS response to test our API's ability to cope
+with invalid data without causing memory corruption.
+
+After building a valid DNS response as normal, we truncate it at the given
+offset.}
+function TNetDbTest.BuildTruncatedQueryData(fdr: TFakeDNSResponse; out
+ qd: TQueryData; out qlen: Word; truncoffset: Word): Boolean;
+var
+ buf: TBuffer;
+begin
+ qlen := FakeDNSResponseToByteBuffer(fdr, buf);
+ qd.h.ancount := HToNs(fdr.hdr.ancount);
+ qd.h.arcount := HToNs(fdr.hdr.arcount);
+ qd.h.nscount := HToNs(fdr.hdr.nscount);
+ qd.h.qdcount := HToNs(fdr.hdr.qdcount);
+ qd.h.flags1 := fdr.hdr.flags1;
+ qd.h.flags2 := fdr.hdr.flags2;
+ qd.h.id[0] := fdr.hdr.id[0];
+ qd.h.id[1] := fdr.hdr.id[1];
+ SetLength(buf, truncoffset);
+ Result := BufferToPayload(buf, qd.Payload);
+end;
+
+initialization
+
+ RegisterTest(TNetDbTest);
+end.
+
diff --git a/avx512-0037785/packages/fcl-net/tests/tresolvertests.pp b/avx512-0037785/packages/fcl-net/tests/tresolvertests.pp
new file mode 100644
index 0000000000..9892dc446b
--- /dev/null
+++ b/avx512-0037785/packages/fcl-net/tests/tresolvertests.pp
@@ -0,0 +1,28 @@
+program tresolvertests;
+
+{$mode objfpc}{$H+}
+
+uses
+ Classes, consoletestrunner, netdbtest;
+
+type
+
+ { TMyTestRunner }
+
+ TMyTestRunner = class(TTestRunner)
+ protected
+ // override the protected methods of TTestRunner to customize its behavior
+ end;
+
+var
+ Application: TMyTestRunner;
+
+begin
+ DefaultFormat:=fPlain;
+ DefaultRunAllTests:=True;
+ Application := TMyTestRunner.Create(nil);
+ Application.Initialize;
+ Application.Title:='resolvertests';
+ Application.Run;
+ Application.Free;
+end.
diff --git a/avx512-0037785/packages/fcl-passrc/src/pasresolver.pp b/avx512-0037785/packages/fcl-passrc/src/pasresolver.pp
index 9fe78b10ff..54f9110705 100644
--- a/avx512-0037785/packages/fcl-passrc/src/pasresolver.pp
+++ b/avx512-0037785/packages/fcl-passrc/src/pasresolver.pp
@@ -3937,10 +3937,16 @@ end;
{ EPasResolve }
procedure EPasResolve.SetPasElement(AValue: TPasElement);
+var
+ Old: TPasElement;
begin
if FPasElement=AValue then Exit;
- if PasElement<>nil then
+ Old:=FPasElement;
+ if Old<>nil then
+ begin
+ Old:=nil;
PasElement.Release{$IFDEF CheckPasTreeRefCount}('EPasResolve.SetPasElement'){$ENDIF};
+ end;
FPasElement:=AValue;
if PasElement<>nil then
PasElement.AddRef{$IFDEF CheckPasTreeRefCount}('EPasResolve.SetPasElement'){$ENDIF};
@@ -7526,11 +7532,13 @@ procedure TPasResolver.FinishExceptOnExpr;
var
El: TPasImplExceptOn;
ResolvedType: TPasResolverResult;
+ TypeEl: TPasType;
begin
CheckTopScope(TPasExceptOnScope);
El:=TPasImplExceptOn(FTopScope.Element);
- ComputeElement(El.TypeEl,ResolvedType,[rcType]);
- CheckIsClass(El.TypeEl,ResolvedType);
+ TypeEl:=El.TypeEl;
+ ComputeElement(TypeEl,ResolvedType,[rcType]);
+ CheckIsClass(TypeEl,ResolvedType);
end;
procedure TPasResolver.FinishExceptOnStatement;
@@ -9049,7 +9057,7 @@ begin
CurEl:=nil;
if not SameText(RightStr(AttrName,length('Attribute')),'Attribute') then
begin
- // first search AttrName+'Attibute'
+ // first search AttrName+'Attribute'
CurEl:=FindFirstEl(AttrName+'Attribute',Data,NameExpr);
end;
// then search the name
@@ -9164,12 +9172,14 @@ var
FindData: TPRFindData;
Ref: TResolvedReference;
ResolvedEl: TPasResolverResult;
+ Section: TPasSection;
+ Scope: TPasIdentifierScope;
+ ScopeIdent: TPasIdentifier;
begin
Expr:=El.NameExpr;
if Expr<>nil then
begin
ResolveExpr(Expr,rraRead);
- //ResolveGlobalSymbol(Expr);
ComputeElement(Expr,ResolvedEl,[rcConstant]);
DeclEl:=ResolvedEl.IdentEl;
if DeclEl=nil then
@@ -9189,9 +9199,21 @@ begin
CheckFoundElement(FindData,Ref);
end;
+ if DeclEl is TPasProcedure then
+ begin
+ Section:=DeclEl.Parent as TPasSection;
+ Scope:=Section.CustomData as TPasIdentifierScope;
+ ScopeIdent:=Scope.FindLocalIdentifier(DeclEl.Name);
+ if (ScopeIdent=nil) then
+ RaiseNotYetImplemented(20210106103001,El,GetObjPath(DeclEl));
+ if ScopeIdent.NextSameIdentifier<>nil then
+ RaiseMsg(20210106103320,nCantDetermineWhichOverloadedFunctionToCall,
+ sCantDetermineWhichOverloadedFunctionToCall,[],El);
+ end;
+
// check index and name
CheckConstExpr(El.ExportIndex,[revkInt,revkUInt],'integer');
- CheckConstExpr(El.ExportName,[revkString,revkUnicodeString],'string');
+ CheckConstExpr(El.ExportName,revkAllStrings,'string');
end;
procedure TPasResolver.FinishProcParamAccess(ProcType: TPasProcedureType;
@@ -12243,6 +12265,7 @@ begin
writeln('TPasResolver.AddExportSymbol ',GetObjName(El));
{$ENDIF}
// Note: export symbol is not added to scope
+ if El=nil then ;
end;
procedure TPasResolver.AddEnumType(El: TPasEnumType);
@@ -18740,54 +18763,67 @@ function TPasResolver.BI_InExclude_OnGetCallCompatibility(
// check params of built in proc 'include'
var
Params: TParamsExpr;
- Param: TPasExpr;
- ParamResolved: TPasResolverResult;
+ Param0, Param1: TPasExpr;
+ Param0Resolved, Param1Resolved: TPasResolverResult;
EnumType: TPasEnumType;
C: TClass;
+ LoTypeEl: TPasType;
+ RgType: TPasRangeType;
begin
if not CheckBuiltInMinParamCount(Proc,Expr,2,RaiseOnError) then
exit(cIncompatible);
Params:=TParamsExpr(Expr);
- // first param: set variable
+ // first Param0: set variable
// todo set of int, set of char, set of bool
- Param:=Params.Params[0];
- ComputeElement(Param,ParamResolved,[rcNoImplicitProc]);
+ Param0:=Params.Params[0];
+ ComputeElement(Param0,Param0Resolved,[rcNoImplicitProc]);
+ Param1:=Params.Params[1];
+ ComputeElement(Param1,Param1Resolved,[]);
+
EnumType:=nil;
- if ([rrfReadable,rrfWritable]*ParamResolved.Flags=[rrfReadable,rrfWritable])
- and (ParamResolved.IdentEl<>nil) then
+ RgType:=nil;
+ if ([rrfReadable,rrfWritable]*Param0Resolved.Flags=[rrfReadable,rrfWritable])
+ and (Param0Resolved.IdentEl<>nil) then
begin
- C:=ParamResolved.IdentEl.ClassType;
+ C:=Param0Resolved.IdentEl.ClassType;
if (C.InheritsFrom(TPasVariable)
or (C=TPasArgument)
or (C=TPasResultElement)) then
begin
- if (ParamResolved.BaseType=btSet)
- and (ParamResolved.LoTypeEl is TPasEnumType) then
- EnumType:=TPasEnumType(ParamResolved.LoTypeEl);
+ if Param0Resolved.BaseType=btSet then
+ begin
+ LoTypeEl:=Param0Resolved.LoTypeEl;
+ if LoTypeEl.ClassType=TPasEnumType then
+ begin
+ EnumType:=TPasEnumType(LoTypeEl);
+ if (not (rrfReadable in Param0Resolved.Flags))
+ or (Param0Resolved.LoTypeEl<>EnumType) then
+ begin
+ if RaiseOnError then
+ RaiseIncompatibleType(20210201225926,nIncompatibleTypeArgNo,
+ ['2'],Param0Resolved.LoTypeEl,EnumType,Param0);
+ exit(cIncompatible);
+ end;
+ end
+ else if LoTypeEl.ClassType=TPasRangeType then
+ begin
+ RgType:=TPasRangeType(LoTypeEl);
+ ComputeElement(RgType.RangeExpr.left,Param0Resolved,[]);
+ Result:=CheckAssignResCompatibility(Param0Resolved,Param1Resolved,Param1,RaiseOnError);
+ end;
+ end;
end;
end;
- if EnumType=nil then
+ if (EnumType=nil) and (RgType=nil) then
begin
{$IFDEF VerbosePasResolver}
- writeln('TPasResolver.OnGetCallCompatibility_InExclude ',GetResolverResultDbg(ParamResolved));
+ writeln('TPasResolver.OnGetCallCompatibility_InExclude ',GetResolverResultDbg(Param0Resolved));
{$ENDIF}
- exit(CheckRaiseTypeArgNo(20170216152301,1,Param,ParamResolved,
+ exit(CheckRaiseTypeArgNo(20170216152301,1,Param0,Param0Resolved,
'variable of set of enumtype',RaiseOnError));
end;
- // second param: enum
- Param:=Params.Params[1];
- ComputeElement(Param,ParamResolved,[]);
- if (not (rrfReadable in ParamResolved.Flags))
- or (ParamResolved.LoTypeEl<>EnumType) then
- begin
- if RaiseOnError then
- RaiseIncompatibleType(20170216152302,nIncompatibleTypeArgNo,
- ['2'],ParamResolved.LoTypeEl,EnumType,Param);
- exit(cIncompatible);
- end;
-
Result:=CheckBuiltInMaxParamCount(Proc,Params,2,RaiseOnError);
end;
@@ -19113,19 +19149,19 @@ begin
exit(cIncompatible);
Params:=TParamsExpr(Expr);
- // first param: bool, enum or char
+ // first param: bool, integer, enum or char
Param:=Params.Params[0];
ComputeElement(Param,ParamResolved,[]);
Result:=cIncompatible;
if rrfReadable in ParamResolved.Flags then
begin
- if ParamResolved.BaseType in (btAllBooleans+btAllChars) then
+ if ParamResolved.BaseType in btArrayRangeTypes then
Result:=cExact
else if (ParamResolved.BaseType=btContext) and (ParamResolved.LoTypeEl is TPasEnumType) then
Result:=cExact
else if ParamResolved.BaseType=btRange then
begin
- if ParamResolved.SubType in btAllBooleans+btAllChars then
+ if ParamResolved.SubType in btArrayRangeTypes then
Result:=cExact
else if ParamResolved.SubType=btContext then
begin
@@ -21318,7 +21354,7 @@ procedure TPasResolver.CheckFoundElement(
// Call this method after finding an element by searching the scopes.
function IsFieldInheritingConst(aRef: TResolvedReference): boolean;
- // returns true of aRef is a TPasVariable that inherits its const from parent.
+ // returns true if aRef is a TPasVariable that inherits its const from parent.
// For example
// type TRecord = record
// a: word; // inherits const
@@ -27564,6 +27600,21 @@ procedure TPasResolver.ComputeElement(El: TPasElement; out
end;
end;
+ procedure ComputeExportSymbol(ExpSymbol: TPasExportSymbol);
+ var
+ Ref: TResolvedReference;
+ begin
+ if ExpSymbol.CustomData is TResolvedReference then
+ begin
+ Ref:=TResolvedReference(El.CustomData);
+ ComputeElement(Ref.Declaration,ResolvedEl,Flags+[rcNoImplicitProc],StartEl);
+ end
+ else if ExpSymbol.NameExpr<>nil then
+ ComputeElement(ExpSymbol.NameExpr,ResolvedEl,Flags,StartEl)
+ else
+ RaiseNotYetImplemented(20210106225512,ExpSymbol);
+ end;
+
var
DeclEl: TPasElement;
ElClass: TClass;
@@ -27946,6 +27997,8 @@ begin
ComputeSpecializeType(TPasSpecializeType(El))
else if ElClass=TInlineSpecializeExpr then
ComputeElement(TInlineSpecializeExpr(El).NameExpr,ResolvedEl,Flags,StartEl)
+ else if ElClass=TPasExportSymbol then
+ ComputeExportSymbol(TPasExportSymbol(El))
else
RaiseNotYetImplemented(20160922163705,El);
{$IF defined(nodejs) and defined(VerbosePasResolver)}
diff --git a/avx512-0037785/packages/fcl-passrc/src/pparser.pp b/avx512-0037785/packages/fcl-passrc/src/pparser.pp
index 59e54088b1..a85d01bb5d 100644
--- a/avx512-0037785/packages/fcl-passrc/src/pparser.pp
+++ b/avx512-0037785/packages/fcl-passrc/src/pparser.pp
@@ -3142,10 +3142,10 @@ begin
FinishedModule;
finally
if HasFinished then
- begin
- Module.Release{$IFDEF CheckPasTreeRefCount}('TPasPackage.Modules'){$ENDIF};
+ //begin
+ //Module.Release{$IFDEF CheckPasTreeRefCount}('TPasPackage.Modules'){$ENDIF};
FCurModule:=nil; // clear module if there is an error or finished parsing
- end;
+ //end;
end;
end;
@@ -6001,10 +6001,23 @@ var
function CloseBlock: boolean; // true if parent reached
var C: TPasImplBlockClass;
+ NeedUnget: Boolean;
begin
C:=TPasImplBlockClass(CurBlock.ClassType);
if C=TPasImplExceptOn then
- Engine.FinishScope(stExceptOnStatement,CurBlock)
+ begin
+ Engine.FinishScope(stExceptOnStatement,CurBlock);
+ NeedUnget:=CurToken=tkSemicolon;
+ if NeedUnget then
+ NextToken;
+ if (CurToken in [tkend,tkelse])
+ or ((CurToken=tkIdentifier) and (lowercase(CurTokenString)='on')) then
+ // ok
+ else
+ ParseExcExpectedAorB('end','on');
+ if NeedUnget then
+ UngetToken;
+ end
else if C=TPasImplWithDo then
Engine.FinishScope(stWithExpr,CurBlock);
CurBlock:=CurBlock.Parent as TPasImplBlock;
@@ -6063,6 +6076,7 @@ var
TypeEl: TPasType;
ImplRaise: TPasImplRaise;
VarEl: TPasVariable;
+ ImplExceptOn: TPasImplExceptOn;
begin
NewImplElement:=nil;
@@ -6486,6 +6500,8 @@ begin
// ParseExc;
CheckStatementCanStart;
+ //writeln('TPasParser.ParseStatement ',CurToken,' ',CurTokenString);
+
// On is usable as an identifier
if lowerCase(CurTokenText)='on' then
begin
@@ -6496,31 +6512,33 @@ begin
begin
SrcPos:=CurTokenPos;
ExpectIdentifier;
- El:=TPasImplExceptOn(CreateElement(TPasImplExceptOn,'',CurBlock,SrcPos));
+ ImplExceptOn:=TPasImplExceptOn(CreateElement(TPasImplExceptOn,'',CurBlock,SrcPos));
+ El:=ImplExceptOn;
SrcPos:=CurSourcePos;
Name:=CurTokenString;
NextToken;
+ //writeln('TPasParser.ParseStatement ',CurToken,' ',CurTokenString);
//writeln('ON t=',Name,' Token=',CurTokenText);
if CurToken=tkColon then
begin
// the first expression was the variable name
NextToken;
- TypeEl:=ParseSimpleType(El,SrcPos,'');
- TPasImplExceptOn(El).TypeEl:=TypeEl;
- VarEl:=TPasVariable(CreateElement(TPasVariable,Name,El,SrcPos));
- TPasImplExceptOn(El).VarEl:=VarEl;
+ TypeEl:=ParseSimpleType(ImplExceptOn,SrcPos,'');
+ ImplExceptOn.TypeEl:=TypeEl;
+ VarEl:=TPasVariable(CreateElement(TPasVariable,Name,ImplExceptOn,SrcPos));
+ ImplExceptOn.VarEl:=VarEl;
VarEl.VarType:=TypeEl;
TypeEl.AddRef{$IFDEF CheckPasTreeRefCount}('TPasVariable.VarType'){$ENDIF};
- if TypeEl.Parent=El then
+ if TypeEl.Parent=ImplExceptOn then
TypeEl.Parent:=VarEl;
end
else
begin
UngetToken;
- TPasImplExceptOn(El).TypeEl:=ParseSimpleType(El,SrcPos,'');
+ ImplExceptOn.TypeEl:=ParseSimpleType(ImplExceptOn,SrcPos,'');
end;
- Engine.FinishScope(stExceptOnExpr,El);
- CreateBlock(TPasImplExceptOn(El));
+ Engine.FinishScope(stExceptOnExpr,ImplExceptOn);
+ CreateBlock(ImplExceptOn);
El:=nil;
ExpectToken(tkDo);
end else
diff --git a/avx512-0037785/packages/fcl-passrc/tests/tcresolver.pas b/avx512-0037785/packages/fcl-passrc/tests/tcresolver.pas
index 587d86c3bf..d7ac1df835 100644
--- a/avx512-0037785/packages/fcl-passrc/tests/tcresolver.pas
+++ b/avx512-0037785/packages/fcl-passrc/tests/tcresolver.pas
@@ -345,6 +345,7 @@ type
Procedure TestTryStatement;
Procedure TestTryExceptOnNonTypeFail;
Procedure TestTryExceptOnNonClassFail;
+ Procedure TestTryStatementMissingOnFail;
Procedure TestRaiseNonVarFail;
Procedure TestRaiseNonClassFail;
Procedure TestRaiseDescendant;
@@ -986,8 +987,8 @@ type
Procedure TestLibrary_ExportFunc_IndexStringFail;
Procedure TestLibrary_ExportVar; // ToDo
Procedure TestLibrary_Initialization_Finalization;
- Procedure TestLibrary_ExportFuncOverloadFail; // ToDo
- // ToDo Procedure TestLibrary_UnitExports;
+ Procedure TestLibrary_ExportFuncOverloadFail;
+ Procedure TestLibrary_UnitExports;
end;
function LinesToStr(Args: array of const): string;
@@ -1736,6 +1737,8 @@ begin
end;
ok:=true;
end;
+ on E: Exception do
+ Fail('Expected EPasResolve but got '+E.ClassName);
end;
AssertEquals('Missing resolver error {'+Msg+'} ('+IntToStr(MsgNumber)+')',true,ok);
end;
@@ -1756,6 +1759,8 @@ begin
MsgNumber,Parser.LastMsgNumber);
ok:=true;
end;
+ on E: Exception do
+ Fail('Expected EParserError but got '+E.ClassName);
end;
AssertEquals('Missing parser error '+Msg+' ('+IntToStr(MsgNumber)+')',true,ok);
end;
@@ -3354,8 +3359,11 @@ begin
' i2: TInt2;',
'begin',
' i:=i2;',
- ' if i=i2 then ;']);
+ ' if i=i2 then ;',
+ ' i:=ord(i);',
+ '']);
ParseProgram;
+ CheckResolverUnexpectedHints;
end;
procedure TTestResolver.TestIntegerRangeHighLowerLowFail;
@@ -4225,7 +4233,9 @@ begin
' s:= {#s3_set}[3..4];',
' s:= {#s4_set}[Three];',
' if 3 in a then ;',
- ' s:=c;']);
+ ' s:=c;',
+ ' Include(s,3);',
+ '']);
ParseProgram;
CheckParamsExpr_pkSet_Markers;
CheckResolverUnexpectedHints;
@@ -5414,6 +5424,23 @@ begin
CheckResolverException('class expected, but Longint found',nXExpectedButYFound);
end;
+procedure TTestResolver.TestTryStatementMissingOnFail;
+begin
+ StartProgram(true,[supTObject]);
+ Add([
+ 'procedure Run;',
+ 'begin',
+ ' try',
+ ' except',
+ ' on TObject do ;',
+ ' Run;',
+ ' end;',
+ 'end;',
+ 'begin',
+ '']);
+ CheckParserException('Expected "end" or "on"',nParserExpectToken2Error);
+end;
+
procedure TTestResolver.TestRaiseNonVarFail;
begin
StartProgram(false);
@@ -18836,8 +18863,6 @@ end;
procedure TTestResolver.TestLibrary_ExportFuncOverloadFail;
begin
- exit;
-
StartLibrary(false);
Add([
'procedure Run(w: word); overload;',
@@ -18850,7 +18875,24 @@ begin
' Run,',
' afile.run;',
'begin']);
- CheckResolverException('The symbol cannot be exported from a library',123);
+ CheckResolverException(sCantDetermineWhichOverloadedFunctionToCall,
+ nCantDetermineWhichOverloadedFunctionToCall);
+end;
+
+procedure TTestResolver.TestLibrary_UnitExports;
+begin
+ StartUnit(false);
+ Add([
+ 'interface' ,
+ 'procedure Run;',
+ 'implementation',
+ 'procedure Run;',
+ 'begin',
+ 'end;',
+ 'exports',
+ ' Run;',
+ '']);
+ ParseUnit;
end;
initialization
diff --git a/avx512-0037785/packages/fcl-registry/fpmake.pp b/avx512-0037785/packages/fcl-registry/fpmake.pp
index b398893b4e..f9a71a0ca0 100644
--- a/avx512-0037785/packages/fcl-registry/fpmake.pp
+++ b/avx512-0037785/packages/fcl-registry/fpmake.pp
@@ -46,8 +46,7 @@ begin
T:=P.Targets.AddUnit('xmlreg.pp');
P.ExamplePath.Add('examples');
- P.Targets.AddExampleProgram('tests/testbasics.pp');
- P.Targets.AddExampleProgram('tests/regtestframework.pp');
+ P.Targets.AddExampleProgram('tests/tregtestframework.pp');
// 'tests/Makefile
// 'tests/Makefile.fpc
diff --git a/avx512-0037785/packages/fcl-registry/src/regini.inc b/avx512-0037785/packages/fcl-registry/src/regini.inc
index 665e24ba4e..4163a57c9b 100644
--- a/avx512-0037785/packages/fcl-registry/src/regini.inc
+++ b/avx512-0037785/packages/fcl-registry/src/regini.inc
@@ -293,31 +293,36 @@ end;
function TRegIniFile.OpenSection(const Section: string; CreateSection : Boolean = false): boolean;
var
- k: HKEY;
- S : String;
-
+ s: string;
begin
- S:=Section;
- If (S<>'') and (S[1] = '\') then
- Delete(S,1,1);
- if CreateSection and (S<>'') then
- CreateKey('\'+CurrentPath+'\'+S);
- if S <> '' then
- k:=GetKey('\'+CurrentPath+'\'+S)
- else
- k:=GetKey('\'+CurrentPath);
- if k = 0 then
- begin
- Result:=False;
- exit;
+ ASSERT(fOldCurKey = 0);
+ if Section <> '' then begin
+ fOldCurKey:=CurrentKey;
+ fOldCurPath:=CurrentPath;
+ // Detach the current key to prevent its closing in OpenKey()
+ SetCurrentKey(0);
+ if Section[1] = '\' then
+ s:=Section
+ else
+ s:='\' + string(fOldCurPath) + '\' + Section;
+ Result:=OpenKey(s, CreateSection);
+ if not Result then begin
+ // Restore on error
+ SetCurrentKey(fOldCurKey);
+ fOldCurKey:=0;
+ fOldCurPath:='';
end;
- SetCurrentKey(k);
- Result:=True;
+ end
+ else
+ Result:=True;
end;
procedure TRegIniFile.CloseSection;
begin
- CloseKey(CurrentKey);
- fCurrentKey:=0;
+ if fOldCurKey <> 0 then begin
+ ChangeKey(fOldCurKey, fOldCurPath);
+ fOldCurKey:=0;
+ fOldCurPath:='';
+ end;
end;
diff --git a/avx512-0037785/packages/fcl-registry/src/registry.pp b/avx512-0037785/packages/fcl-registry/src/registry.pp
index 7f11182b05..91177376e1 100644
--- a/avx512-0037785/packages/fcl-registry/src/registry.pp
+++ b/avx512-0037785/packages/fcl-registry/src/registry.pp
@@ -202,6 +202,8 @@ type
fFileName : String;
fPath : String;
fPreferStringValues: Boolean;
+ fOldCurKey : HKEY;
+ fOldCurPath : UnicodeString;
function OpenSection(const Section: string; CreateSection : Boolean = false): boolean;
procedure CloseSection;
public
@@ -266,6 +268,7 @@ type
procedure DeleteKey(const Section, Name: String); override;
procedure UpdateFile; override;
function ValueExists(const Section, Ident: string): Boolean; override;
+ function SectionExists(const Section: string): Boolean; override;
property RegIniFile: TRegIniFile read FRegIniFile;
end{$ifdef XMLREG}deprecated 'Use TRegistry instead. Will be removed in 4.0'{$endif} platform;
@@ -1125,13 +1128,18 @@ end;
function TRegistryIniFile.ValueExists(const Section, Ident: string): Boolean;
begin
- with FRegInifile do
- if OpenSection(Section) then
- try
- Result:=FRegInifile.ValueExists(Ident);
- finally
- CloseSection;
- end;
+ Result:=FRegInifile.OpenSection(Section);
+ if Result then
+ try
+ Result:=FRegInifile.ValueExists(Ident);
+ finally
+ FRegInifile.CloseSection;
+ end;
+end;
+
+function TRegistryIniFile.SectionExists(const Section: string): Boolean;
+begin
+ Result:=FRegIniFile.KeyExists(Section);
end;
{$ifdef XMLREG}
diff --git a/avx512-0037785/packages/fcl-registry/src/winreg.inc b/avx512-0037785/packages/fcl-registry/src/winreg.inc
index f4efdc88d3..3fa014d1a3 100644
--- a/avx512-0037785/packages/fcl-registry/src/winreg.inc
+++ b/avx512-0037785/packages/fcl-registry/src/winreg.inc
@@ -81,7 +81,28 @@ function TRegistry.DeleteKey(const Key: UnicodeString): Boolean;
Var
u: UnicodeString;
+ subkeys: TUnicodeStringArray;
+ k, old: HKEY;
+ i: integer;
begin
+ old:=fCurrentKey;
+ k:=GetKey(Key);
+ if k <> 0 then
+ begin
+ fCurrentKey:=k;
+ try
+ subkeys:=GetKeyNames;
+ for i:=0 to High(subkeys) do
+ begin
+ Result:=DeleteKey(subkeys[i]);
+ if not Result then
+ exit;
+ end;
+ finally
+ fCurrentKey:=old;
+ CloseKey(k);
+ end;
+ end;
u:=PRepKey(Key);
FLastError:=RegDeleteKeyW(GetBaseKey(RelativeKey(Key)),PWideChar(u));
Result:=FLastError=ERROR_SUCCESS;
diff --git a/avx512-0037785/packages/fcl-registry/src/xmlreg.pp b/avx512-0037785/packages/fcl-registry/src/xmlreg.pp
index 7b661e5922..961c599878 100644
--- a/avx512-0037785/packages/fcl-registry/src/xmlreg.pp
+++ b/avx512-0037785/packages/fcl-registry/src/xmlreg.pp
@@ -235,23 +235,13 @@ end;
Function TXmlRegistry.DeleteKey(KeyPath : UnicodeString) : Boolean;
Var
- N, Curr : TDomElement;
- Node: TDOMNode;
+ N : TDomElement;
begin
N:=FindKey(KeyPath);
Result:=(N<>Nil);
If Result then
begin
- //if a key has subkeys, result shall be false and nothing shall be deleted
- Curr:=N;
- Node:=Curr.FirstChild;
- While Assigned(Node) do
- begin
- If (Node.NodeType=ELEMENT_NODE) and (Node.NodeName=SKey) then
- Exit(False);
- Node:=Node.NextSibling;
- end;
(N.ParentNode as TDomElement).RemoveChild(N);
FDirty:=True;
MaybeFlush;
@@ -269,6 +259,8 @@ begin
Result:=(Length(KeyPath)>0);
If Not Result then
Exit;
+ If (KeyPath[1] in ['/','\']) then
+ FCurrentElement:=Nil;
KeyPath:=NormalizeKey(KeyPath);
If (FCurrentElement<>nil) then
begin
@@ -917,6 +909,8 @@ begin
Result:=Nil;
If (Length(S)=0) then
Exit;
+ if S[1] in ['/','\'] then
+ FCurrentElement:=nil;
S:=NormalizeKey(S);
If (FCurrentElement<>nil) then
begin
diff --git a/avx512-0037785/packages/fcl-registry/tests/Makefile b/avx512-0037785/packages/fcl-registry/tests/Makefile
index fbf4d80011..e4c98af0e8 100644
--- a/avx512-0037785/packages/fcl-registry/tests/Makefile
+++ b/avx512-0037785/packages/fcl-registry/tests/Makefile
@@ -350,316 +350,316 @@ endif
override PACKAGE_NAME=fcl
PACKAGEDIR_MAIN:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /fcl/Makefile.fpc,$(PACKAGESDIR))))))
ifeq ($(FULL_TARGET),i386-linux)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),i386-go32v2)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),i386-win32)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),i386-os2)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),i386-freebsd)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),i386-beos)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),i386-haiku)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),i386-netbsd)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),i386-solaris)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),i386-netware)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),i386-openbsd)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),i386-wdosx)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),i386-darwin)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),i386-emx)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),i386-watcom)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),i386-netwlibc)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),i386-wince)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),i386-embedded)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),i386-symbian)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),i386-nativent)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),i386-iphonesim)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),i386-android)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),i386-aros)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),m68k-linux)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),m68k-netbsd)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),m68k-amiga)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),m68k-atari)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),m68k-palmos)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),m68k-macosclassic)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),m68k-embedded)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),m68k-sinclairql)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),powerpc-linux)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),powerpc-netbsd)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),powerpc-amiga)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),powerpc-macosclassic)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),powerpc-darwin)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),powerpc-morphos)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),powerpc-embedded)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),powerpc-wii)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),powerpc-aix)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),sparc-linux)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),sparc-netbsd)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),sparc-solaris)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),sparc-embedded)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),x86_64-linux)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),x86_64-freebsd)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),x86_64-haiku)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),x86_64-netbsd)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),x86_64-solaris)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),x86_64-openbsd)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),x86_64-darwin)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),x86_64-win64)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),x86_64-embedded)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),x86_64-iphonesim)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),x86_64-android)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),x86_64-aros)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),x86_64-dragonfly)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),arm-linux)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),arm-netbsd)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),arm-palmos)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),arm-wince)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),arm-gba)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),arm-nds)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),arm-embedded)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),arm-symbian)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),arm-android)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),arm-aros)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),arm-freertos)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),arm-ios)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),powerpc64-linux)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),powerpc64-darwin)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),powerpc64-embedded)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),powerpc64-aix)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),avr-embedded)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),armeb-linux)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),armeb-embedded)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),mips-linux)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),mipsel-linux)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),mipsel-embedded)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),mipsel-android)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),mips64el-linux)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),jvm-java)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),jvm-android)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),i8086-embedded)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),i8086-msdos)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),i8086-win16)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),aarch64-linux)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),aarch64-darwin)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),aarch64-win64)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),aarch64-android)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),aarch64-ios)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),wasm-wasm)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),sparc64-linux)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),riscv32-linux)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),riscv32-embedded)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),riscv64-linux)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),riscv64-embedded)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),xtensa-linux)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),xtensa-embedded)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),xtensa-freertos)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),z80-embedded)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),z80-zxspectrum)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),z80-msxdos)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
ifeq ($(FULL_TARGET),z80-amstradcpc)
-override TARGET_EXAMPLES+=regtestframework
+override TARGET_EXAMPLES+=tregtestframework
endif
override INSTALL_FPCPACKAGE=y
ifdef REQUIRE_UNITSDIR
diff --git a/avx512-0037785/packages/fcl-registry/tests/Makefile.fpc b/avx512-0037785/packages/fcl-registry/tests/Makefile.fpc
index 724f61968b..7293b10223 100644
--- a/avx512-0037785/packages/fcl-registry/tests/Makefile.fpc
+++ b/avx512-0037785/packages/fcl-registry/tests/Makefile.fpc
@@ -1,12 +1,12 @@
#
-# Makefile.fpc for DB TestFramework
+# Makefile.fpc for Registry TestFramework
#
[package]
main=fcl
[target]
-examples=regtestframework
+examples=tregtestframework
[install]
fpcpackage=y
diff --git a/avx512-0037785/packages/fcl-registry/tests/tcxmlreg.pp b/avx512-0037785/packages/fcl-registry/tests/regtcxmlreg.pp
index 273a09ac8e..2de0ddb4fe 100644
--- a/avx512-0037785/packages/fcl-registry/tests/tcxmlreg.pp
+++ b/avx512-0037785/packages/fcl-registry/tests/regtcxmlreg.pp
@@ -1,4 +1,4 @@
-unit tcxmlreg;
+unit regtcxmlreg;
{$mode objfpc}{$H+}
@@ -39,6 +39,7 @@ end;
procedure TTestXMLRegistry.TearDown;
begin
FreeAndNil(FXMLReg);
+ DeleteFile('test.xml');
inherited TearDown;
end;
@@ -93,13 +94,13 @@ begin
SetLength(S1,100);
For I:=0 to 99 do
S1[I]:=i;
- XMLReg.SetValueData('b',dtBinary,S1[1],Length(S1));
+ XMLReg.SetValueData('b',dtBinary,S1[0],Length(S1));
XMLReg.Flush;
- DS:=SizeOf(S1) div 4;
+ DS:=Length(S1) div 4;
SetLength(S2,DS);
For I:=0 to DS-1 do
S2[I]:=i;
- AssertEquals('Cannot read, buffer size too small',False,XMLReg.GetValueData('b',dt,S2[1],ds));
+ AssertEquals('Cannot read, buffer size too small',False,XMLReg.GetValueData('b',dt,S2[0],DS));
AssertTrue('Correct data type reported',dt=dtBinary);
AssertEquals('Correct data buffer size reported',Length(S1),DS);
end;
diff --git a/avx512-0037785/packages/fcl-registry/tests/testbasics.pp b/avx512-0037785/packages/fcl-registry/tests/regtestbasics.pp
index dfe4eb193b..bddc3bcd17 100644
--- a/avx512-0037785/packages/fcl-registry/tests/testbasics.pp
+++ b/avx512-0037785/packages/fcl-registry/tests/regtestbasics.pp
@@ -1,4 +1,4 @@
-unit TestBasics;
+unit RegTestBasics;
{$IFDEF FPC}
{$mode objfpc}{$H+}
@@ -21,7 +21,6 @@ type
procedure TestSimpleWinRegistry;
procedure TestDoubleWrite;
procedure bug16395;
- procedure TestAdv;
procedure TestStringList;
Procedure TestInt64;
Procedure TestDeleteSubkey;
@@ -30,11 +29,7 @@ type
implementation
uses
- registry
-{$ifdef windows}
- , tregistry2
-{$endif windows}
- ;
+ registry;
{ TTestBasics }
@@ -167,13 +162,6 @@ begin
DeleteUserXmlFile;
end;
-procedure TTestBasics.TestAdv;
-begin
-{$ifdef windows}
- DoRegTest2;
-{$endif windows}
-end;
-
Procedure TTestBasics.TestStringList;
Var
@@ -278,7 +266,7 @@ begin
AssertTrue(format('OpenKey(''%s'') failed.',[Base]),B);
B := R.DeleteKey('One');
- AssertFalse(format('DeleteKey(''%s'') should have failed, but it succeeded.',[OneFull]),B);
+ AssertTrue(format('DeleteKey(''%s'') should have succeeded, but it failed.',[OneFull]),B);
finally
R.Free;
CleanUp(ExceptObject <> nil);
diff --git a/avx512-0037785/packages/fcl-registry/tests/tregistry2.pp b/avx512-0037785/packages/fcl-registry/tests/tregistry2.pp
index 7cc6a24411..e0ca983ae3 100644
--- a/avx512-0037785/packages/fcl-registry/tests/tregistry2.pp
+++ b/avx512-0037785/packages/fcl-registry/tests/tregistry2.pp
@@ -1,33 +1,47 @@
-{$ifdef FPC} {$mode delphi} {$endif}
-unit tregistry2;
-
-interface
+{ %TARGET=win32,win64,wince,linux,solaris,openbsd }
-procedure DoRegTest2;
+{
+ This unit tests mostly TRegIniFile to work properly and be Delphi compatible.
+ This test also runs on non-Windows platforms where XML registry is used.
+ Please keep this test Delphi compatible.
+}
-implementation
+{$ifdef FPC} {$mode delphi} {$endif}
+uses
+{$ifdef unix}
+ cwstring,
+{$endif unix}
+ SysUtils, Classes, registry;
-uses Windows, SysUtils, Classes, registry;
+{$ifdef FPC}
+ {$WARN implicit_string_cast_loss off}
+ {$WARN symbol_deprecated off}
+{$endif FPC}
const
STestRegPath = 'Software\FPC-RegTest';
procedure TestFailed(ErrCode: integer);
begin
- raise Exception.Create('Test FAILED. Error code: ' + IntToStr(ErrCode));
+ writeln('Test FAILED. Error code: ' + IntToStr(ErrCode));
+ Halt(ErrCode);
end;
-procedure ClearReg;
+procedure ClearReg(const KeyName: string = '');
begin
with TRegistry.Create do
try
- DeleteKey(STestRegPath + '\1');
DeleteKey(STestRegPath);
finally
Free;
end;
end;
+function NormPath(const s: string): string;
+begin
+ Result:=StringReplace(s, '/', '\', [rfReplaceAll]);
+end;
+
procedure DoRegTest2;
var
reg: TRegistry;
@@ -36,33 +50,47 @@ var
sl: TStringList;
begin
ClearReg;
- reg:=TRegistry.Create;
try
- if not reg.OpenKey(STestRegPath, True) then
- TestFailed(1);
- if reg.CurrentPath <> STestRegPath then
- TestFailed(2);
- reg.WriteString('Item1', '1');
- if not reg.OpenKey('\' + STestRegPath + '\1', True) then
- TestFailed(3);
- reg.WriteString('Item2', '2');
- if reg.CurrentPath <> STestRegPath + '\1' then
- TestFailed(5);
- reg.CloseKey;
- if reg.CurrentPath <> '' then
- TestFailed(6);
+ reg:=TRegistry.Create;
+ try
+ { The test key must be deleted by ClearReg() }
+ if reg.KeyExists(STestRegPath) then
+ TestFailed(1);
+ if reg.OpenKey(STestRegPath, False) then
+ TestFailed(2);
+
+ if not reg.OpenKey(STestRegPath, True) then
+ TestFailed(5);
+ if NormPath(reg.CurrentPath) <> STestRegPath then
+ TestFailed(6);
+ reg.WriteString('Item1', '1');
+ if not reg.OpenKey('\' + STestRegPath + '\1', True) then
+ TestFailed(10);
+ reg.WriteString('Item2', '2');
+ if NormPath(reg.CurrentPath) <> STestRegPath + '\1' then
+ TestFailed(15);
+ reg.CloseKey;
+ if NormPath(reg.CurrentPath) <> '' then
+ TestFailed(20);
+ if reg.KeyExists(STestRegPath + '\' + STestRegPath) then
+ TestFailed(21);
+ finally
+ reg.Free;
+ end;
ri:=TRegIniFile.Create(STestRegPath);
with ri do
try
if ReadString('', 'Item1', '') <> '1' then
- TestFailed(10);
+ TestFailed(101);
if ReadString('1', 'Item2', '') <> '2' then
- TestFailed(11);
+ TestFailed(105);
+ if NormPath(ri.CurrentPath) <> STestRegPath then
+ TestFailed(110);
if ReadString('', 'Item1', '') <> '1' then
- TestFailed(12);
+ TestFailed(115);
if not ValueExists('Item1') then
- TestFailed(13);
+ TestFailed(120);
WriteInteger('1', 'Item3', 3);
@@ -70,44 +98,133 @@ begin
try
ReadSectionValues('1', sl);
if sl.Count <> 2 then
- TestFailed(14);
+ TestFailed(125);
if sl.Values['Item2'] <> '2' then
- TestFailed(15);
+ TestFailed(130);
if sl.Values['Item3'] <> '3' then
- TestFailed(16);
+ TestFailed(135);
finally
sl.Free;
end;
WriteInteger('', 'Item4', 4);
- if GetDataType('Item4') <> rdString then
- TestFailed(17);
+ WriteInteger('', 'Item41', 41);
+ WriteInteger('', 'Item42', 42);
+ if GetDataType('Item4') <> rdString then
+ TestFailed(140);
+ if ReadString('', 'Item41', '') <> '41' then
+ TestFailed(141);
+ if ReadString('', 'Item42', '') <> '42' then
+ TestFailed(142);
+ finally
+ Free;
+ end;
+
+ { \ at the beginning of the path must be accepted }
+ ri:=TRegIniFile.Create('\' + STestRegPath);
+ with ri do
+ try
+ if ReadString('', 'Item1', '') <> '1' then
+ TestFailed(145);
finally
Free;
end;
+ { Write to non-existing key must work }
+ ri:=TRegIniFile.Create(STestRegPath + '\2\3\4');
+ with ri do
+ try
+ if FileName <> NormPath(CurrentPath) then
+ TestFailed(147);
+ if CurrentKey = 0 then
+ TestFailed(148);
+ WriteInteger('', 'Item5', 5);
+ WriteInteger('5', 'Item6', 6);
+ if ReadInteger('', 'Item5', 0) <> 5 then
+ TestFailed(150);
+ if ReadInteger('5', 'Item6', 0) <> 6 then
+ TestFailed(160);
+ finally
+ Free;
+ end;
+
+
rini:=TRegistryIniFile.Create(STestRegPath);
with rini do
try
if ReadString('', 'Item1', '') <> '1' then
- TestFailed(20);
+ TestFailed(201);
+ { \ is not allowed as a section name }
+ if ReadString('\', 'Item1', '') = '1' then
+ TestFailed(202);
if ReadString('1', 'Item2', '') <> '2' then
- TestFailed(21);
+ TestFailed(205);
+ { Trailing \ is allowed }
+ if ReadString('1\', 'Item2', '') <> '2' then
+ TestFailed(206);
if ReadString('', 'Item1', '') <> '1' then
- TestFailed(22);
+ TestFailed(210);
if not ValueExists('', 'Item4') then
- TestFailed(23);
+ TestFailed(215);
if not ValueExists('1', 'Item2') then
- TestFailed(24);
+ TestFailed(220);
+ if ReadInteger('2\3\4\5', 'Item6', 0) <> 6 then
+ TestFailed(225);
+ if ReadInteger('2\3\4', 'Item5', 0) <> 5 then
+ TestFailed(230);
+
+ EraseSection('2');
+ if SectionExists('2\3') then
+ TestFailed(245);
+ if ValueExists('2\3\4', 'Item5') then
+ TestFailed(240);
+
+ WriteString('2\3\4', 'Item10', '10');
+ if ReadInteger('2\3\4', 'Item10', 0) <> 10 then
+ TestFailed(245);
+
+ { Check access via a full path }
+ if not SectionExists('\' + STestRegPath) then
+ TestFailed(250);
+ if ReadInteger('\2\3\4', 'Item10', 0) = 10 then
+ TestFailed(255);
+ if ReadInteger('\' + STestRegPath + '\2\3\4', 'Item10', 0) <> 10 then
+ TestFailed(260);
finally
Free;
end;
finally
- reg.Free;
ClearReg;
end;
+
+ { Test if all test keys have been deleted by ClearReg() }
+ reg:=TRegistry.Create;
+ try
+ if reg.KeyExists(STestRegPath) then
+ TestFailed(501);
+ if reg.OpenKey(STestRegPath, False) then
+ TestFailed(502);
+ if reg.OpenKey(STestRegPath + '\2', False) then
+ TestFailed(503);
+ finally
+ reg.Free;
+ end;
+end;
+
+procedure DeleteUserXmlFile;
+begin
+{$ifdef FPC}
+ DeleteFile(Includetrailingpathdelimiter(GetAppConfigDir(False))+'reg.xml');
+ RemoveDir(GetAppConfigDir(False));
+{$endif FPC}
end;
+begin
+ try
+ DoRegTest2;
+ finally
+ DeleteUserXmlFile;
+ end;
end.
diff --git a/avx512-0037785/packages/fcl-registry/tests/regtestframework.pp b/avx512-0037785/packages/fcl-registry/tests/tregtestframework.pp
index 49c3222a34..f8420857a3 100644
--- a/avx512-0037785/packages/fcl-registry/tests/regtestframework.pp
+++ b/avx512-0037785/packages/fcl-registry/tests/tregtestframework.pp
@@ -1,34 +1,35 @@
-program regtestframework;
-
-{$IFDEF FPC}
-{$mode objfpc}{$H+}
-{$ENDIF}
-
-{$IFDEF WINDOWS}
-{$APPTYPE CONSOLE}
-{$ENDIF}
-
-uses
- {$ifdef unix}
- cwstring,
- {$endif}
- SysUtils,
- fpcunit, testreport, testregistry, consoletestrunner,
-// Units wich contains the tests
- tcxmlreg,
- testbasics;
-
-Var
- A : TTestRunner;
-
-begin
- DefaultFormat:=fPlain;
- DefaultRunAllTests:=True;
- A:=TTestRunner.Create(Nil);
- try
- A.Initialize;
- A.Run;
- finally
- A.Free;
- end;
-end.
+{ %TARGET=win32,win64,wince,linux,solaris,openbsd }
+program tregtestframework;
+
+{$IFDEF FPC}
+{$mode objfpc}{$H+}
+{$ENDIF}
+
+{$IFDEF WINDOWS}
+{$APPTYPE CONSOLE}
+{$ENDIF}
+
+uses
+ {$ifdef unix}
+ cwstring,
+ {$endif}
+ SysUtils,
+ fpcunit, testreport, testregistry, consoletestrunner,
+// Units wich contains the tests
+ regtcxmlreg,
+ regtestbasics;
+
+Var
+ A : TTestRunner;
+
+begin
+ DefaultFormat:=fPlain;
+ DefaultRunAllTests:=True;
+ A:=TTestRunner.Create(Nil);
+ try
+ A.Initialize;
+ A.Run;
+ finally
+ A.Free;
+ end;
+end.
diff --git a/avx512-0037785/packages/fcl-stl/src/gdeque.pp b/avx512-0037785/packages/fcl-stl/src/gdeque.pp
index c620188000..ac106e5581 100644
--- a/avx512-0037785/packages/fcl-stl/src/gdeque.pp
+++ b/avx512-0037785/packages/fcl-stl/src/gdeque.pp
@@ -14,6 +14,11 @@
unit gdeque;
+{
+ Implements a generic double ended queue.
+ (See: https://en.wikipedia.org/wiki/Double-ended_queue)
+}
+
interface
type
@@ -30,10 +35,18 @@ type
procedure SetValue(position:SizeUInt; value:T);inline;
function GetValue(position:SizeUInt):T;inline;
function GetMutable(position:SizeUInt):PT;inline;
- procedure IncreaseCapacity();inline;
+ procedure IncreaseCapacity();
+ protected
+ procedure MoveSimpleData(StartIndex: SizeUInt; Offset: SizeInt; NrElems: SizeUInt);
+ procedure MoveManagedData(StartIndex: SizeUInt; Offset: SizeInt; NrElems: SizeUInt);
+ procedure MoveData(StartIndex: SizeUInt; Offset: SizeInt; NrElems: SizeUInt);
+ procedure ClearSingleDataEntry(Index: SizeUInt); virtual;
+ procedure ClearData; virtual;
+ property Data: TArr read FData;
public
function Size():SizeUInt;inline;
constructor Create();
+ destructor Destroy(); override;
Procedure Clear;
procedure PushBack(value:T);inline;
procedure PushFront(value:T);inline;
@@ -59,8 +72,15 @@ begin
FStart:=0;
end;
+destructor TDeque.Destroy();
+begin
+ Clear;
+ inherited Destroy;
+end;
+
procedure TDeque.Clear;
begin
+ ClearData;
FDataSize:=0;
FStart:=0;
end;
@@ -87,6 +107,7 @@ procedure TDeque.PopFront();inline;
begin
if(FDataSize>0) then
begin
+ ClearSingleDataEntry(FStart);
inc(FStart);
dec(FDataSize);
if(FStart=FCapacity) then
@@ -97,7 +118,10 @@ end;
procedure TDeque.PopBack();inline;
begin
if(FDataSize>0) then
+ begin
+ ClearSingleDataEntry((FStart+FDataSize-1)mod FCapacity);
dec(FDataSize);
+ end;
end;
procedure TDeque.PushFront(value:T);inline;
@@ -127,6 +151,7 @@ end;
procedure TDeque.SetValue(position:SizeUInt; value:T);inline;
begin
Assert(position < size, 'Deque access out of range');
+ ClearSingleDataEntry((FStart+position)mod FCapacity);
FData[(FStart+position)mod FCapacity]:=value;
end;
@@ -142,7 +167,68 @@ begin
GetMutable:=@FData[(FStart+position) mod FCapacity];
end;
-procedure TDeque.IncreaseCapacity;inline;
+
+procedure TDeque.MoveSimpleData(StartIndex: SizeUInt; Offset: SizeInt; NrElems: SizeUInt);
+begin
+ Move(FData[StartIndex], FData[StartIndex+Offset], NrElems*SizeOf(T));
+ if Offset>0 then
+ FillChar(FData[StartIndex], NrElems*SizeOf(T), 0)
+ else
+ FillChar(FData[StartIndex+NrElems+Offset], -Offset*SizeOf(T), 0);
+end;
+
+procedure TDeque.MoveManagedData(StartIndex: SizeUInt; Offset: SizeInt; NrElems: SizeUInt);
+var
+ i: SizeUInt;
+begin
+ //since we always move blocks where Abs(Offset)>=NrElems, there is no need for
+ //2 seperate loops (1 for ngeative and 1 for positive Offsett)
+ for i := 0 to NrElems-1 do
+ begin
+ Finalize(FData[StartIndex+i+Offset]);
+ FData[StartIndex+i+Offset] := FData[StartIndex+i];
+ Finalize(FData[StartIndex+i]);
+ FillChar(FData[StartIndex+i], SizeOf(T), 0);
+ end;
+end;
+
+procedure TDeque.MoveData(StartIndex: SizeUInt; Offset: SizeInt; NrElems: SizeUInt);
+begin
+ if IsManagedType(T) then
+ MoveManagedData(StartIndex, Offset, NrElems)
+ else
+ MoveSimpleData(StartIndex, Offset, NrElems);
+end;
+
+procedure TDeque.ClearSingleDataEntry(Index: SizeUInt);
+begin
+ if IsManagedType(T) then
+ begin
+ Finalize(FData[Index]);
+ FillChar(FData[Index], SizeOf(T), 0);
+ end
+ else
+ FData[Index] := default(T);
+end;
+
+procedure TDeque.ClearData;
+var
+ i: SizeUint;
+begin
+ if IsManagedType(T) then
+ for i := Low(FData) to High(FData) do
+ Finalize(FData[i]);
+ FillChar(FData[Low(FData)], SizeUInt(Length(FData))*SizeOf(T), 0);
+end;
+
+procedure TDeque.IncreaseCapacity;
+ function Min(const A,B: SizeUInt): SizeUInt; inline; //no need to drag in the entire Math unit ;-)
+ begin
+ if (A<B) then
+ Result:=A
+ else
+ Result:=B;
+ end;
const
// if size is small, multiply by 2;
// if size bigger but <256M, inc by 1/8*size;
@@ -151,7 +237,7 @@ const
cSizeBig = 256*1024*1024;
var
i,OldEnd,
- DataSize:SizeUInt;
+ DataSize,CurLast,EmptyElems,Elems:SizeUInt;
begin
OldEnd:=FCapacity;
DataSize:=FCapacity*SizeOf(T);
@@ -165,11 +251,26 @@ begin
FCapacity:=FCapacity+FCapacity div 8
else
FCapacity:=FCapacity+FCapacity div 16;
-
SetLength(FData, FCapacity);
if (FStart>0) then
- for i:=0 to FStart-1 do
- FData[OldEnd+i]:=FData[i];
+ begin
+ if (FCapacity-OldEnd>=FStart) then //we have room to move all items in one go
+ begin
+ MoveData(0, OldEnd ,FStart)
+ end
+ else
+ begin //we have to move things around in chunks: we have more data in front of FStart than we have newly created unused elements
+ CurLast := OldEnd-1;
+ EmptyElems:=FCapacity-1-CurLast;
+ while (FStart>0) do
+ begin
+ Elems := Min(EmptyElems, FStart);
+ MoveData(0, CurLast+1, Elems);
+ MoveData(Elems, -Elems, FCapacity-Elems);
+ Dec(FStart, Elems);
+ end;
+ end;
+ end;
end;
procedure TDeque.Reserve(cap:SizeUInt);inline;
diff --git a/avx512-0037785/packages/fpmkunit/src/fpmkunit.pp b/avx512-0037785/packages/fpmkunit/src/fpmkunit.pp
index f858a90c65..d8bc9a4016 100644
--- a/avx512-0037785/packages/fpmkunit/src/fpmkunit.pp
+++ b/avx512-0037785/packages/fpmkunit/src/fpmkunit.pp
@@ -1059,8 +1059,12 @@ Type
FOptions: TStrings;
FCPU: TCPU;
FOS: TOS;
+ FSourceCPU: TCPU;
+ FSourceOS: TOS;
FMode : TCompilerMode;
+ FCompilerDate : String;
FCompilerVersion : String;
+ FFullCompilerVersion : String;
FPrefix: String;
FBaseInstallDir,
FUnitInstallDir,
@@ -1134,7 +1138,11 @@ Type
Property Target : String Read FTarget Write SetTarget;
Property OS : TOS Read FOS Write SetOS;
Property CPU : TCPU Read FCPU Write SetCPU;
+ Property SourceOS : TOS Read FSourceOS;
+ Property SourceCPU : TCPU Read FSourceCPU;
Property CompilerVersion : String read FCompilerVersion;
+ Property CompilerDate : String read FCompilerDate;
+ Property FullCompilerVersion : String read FFullCompilerVersion;
Property ExplicitOSNone: Boolean read FExplicitOSNone Write FExplicitOSNone;
Property BuildString : String read GetBuildString;
Property BuildOS : TOS read GetBuildOS;
@@ -1774,6 +1782,7 @@ ResourceString
SWarnExtCommandNotFound = 'Warning: External command "%s" not found but "%s" is older then "%s"';
SWarnDuplicatePackage = 'Warning: Package %s is already added. Using the existing package';
SWarngccNotFound = 'Could not find libgcc';
+ SWarncrossgccNotFound = 'Could not find libgcc for cross-configuration';
SWarngcclibpath = 'Warning: Unable to determine the libgcc path.';
SWarnNoFCLProcessSupport= 'No FCL-Process support';
SWarnRetryRemDirectory = 'Failed to remove directory "%s". Retry after a short delay';
@@ -2838,6 +2847,12 @@ end;
function GetDefaultLibGCCDir(CPU : TCPU;OS: TOS; var ErrorMessage: string): string;
+var
+ CrossPrefix: string;
+ UseBinutilsPrefix: boolean;
+ SourceOS : TOS;
+ SourceCPU : TCPU;
+
function Get4thWord(const AString: string): string;
var p: pchar;
spacecount: integer;
@@ -2874,7 +2889,7 @@ function GetDefaultLibGCCDir(CPU : TCPU;OS: TOS; var ErrorMessage: string): stri
GccExecutable: string;
begin
result := '';
- GccExecutable := ExeSearch(AddProgramExtension('gcc', OS),Sysutils.GetEnvironmentVariable('PATH'));
+ GccExecutable := ExeSearch(AddProgramExtension(CrossPrefix+'gcc', OS),Sysutils.GetEnvironmentVariable('PATH'));
if FileExists(GccExecutable) then
begin
{$ifdef HAS_UNIT_PROCESS}
@@ -2894,6 +2909,8 @@ function GetDefaultLibGCCDir(CPU : TCPU;OS: TOS; var ErrorMessage: string): stri
ErrorMessage := SWarnNoFCLProcessSupport;
{$endif HAS_UNIT_PROCESS}
end
+ else if UseBinutilsPrefix then
+ ErrorMessage := SWarncrossgccNotFound
else
ErrorMessage := SWarngccNotFound;
end;
@@ -2901,10 +2918,53 @@ function GetDefaultLibGCCDir(CPU : TCPU;OS: TOS; var ErrorMessage: string): stri
begin
result := '';
ErrorMessage:='';
+ if assigned(Defaults) then
+ begin
+ SourceOS:=Defaults.SourceOS;
+ SourceCPU:=Defaults.SourceCPU;
+ end
+ else
+ begin
+ SourceOS:=StringToOS({$I %FPCTARGETOS%});
+ SourceCPU:=StringToCPU({$I %FPCTARGETCPU%});
+ end;
+
+ if (SourceOS<>OS) then
+ UseBinutilsPrefix:=true;
+ if (SourceCPU<>CPU) then
+ begin
+ { we need to accept 32<->64 conversion }
+ { expect for OpenBSD which does not allow this }
+ if not(
+ ((SourceCPU=aarch64) and (CPU=arm)) or
+ ((SourceCPU=powerpc64) and (CPU=powerpc)) or
+ ((SourceCPU=x86_64) and (CPU=i386)) or
+ ((SourceCPU=riscv64) and (CPU=riscv32)) or
+ ((SourceCPU=sparc64) and (CPU=sparc)) or
+ ((CPU=aarch64) and (SourceCPU=arm)) or
+ ((CPU=powerpc64) and (SourceCPU=powerpc)) or
+ ((CPU=x86_64) and (SourceCPU=i386)) or
+ ((CPU=riscv64) and (SourceCPU=riscv32)) or
+ ((CPU=sparc64) and (SourceCPU=sparc))
+ ) or (SourceOS=openbsd) then
+ UseBinutilsPrefix:=true;
+ end;
+ if not UseBinutilsPrefix then
+ CrossPrefix:=''
+ else if Sysutils.GetEnvironmentVariable('BINUTILSPREFIX')<>'' then
+ CrossPrefix:=Sysutils.GetEnvironmentVariable('BINUTILSPREFIX')
+ else
+ CrossPrefix:=CPUToString(CPU)+'-'+OSToString(OS)+'-';
if OS in [freebsd, openbsd, dragonfly] then
- result := '/usr/local/lib'
+ begin
+ if CrossPrefix='' then
+ result := '/usr/local/lib'
+ end
else if OS = netbsd then
- result := '/usr/pkg/lib'
+ begin
+ if CrossPrefix='' then
+ result := '/usr/pkg/lib'
+ end
else if OS = linux then
case CPU of
i386: result := GetGccDirArch('cpui386','-m32');
@@ -3323,9 +3383,8 @@ begin
end;
procedure TCompileWorkerThread.execute;
-begin
- while not Terminated do
- begin
+ procedure RaiseMainEvent;
+ begin
{ Make sure all of our results are committed before we set (F)Done to true.
While RTLeventSetEvent implies a barrier, once the main thread is notified
it will walk over all threads and look for those that have Done=true -> it
@@ -3334,6 +3393,12 @@ begin
WriteBarrier;
FDone:=true;
RTLeventSetEvent(FNotifyMainThreadEvent);
+ end;
+begin
+ if not Terminated then
+ RaiseMainEvent;
+ while not Terminated do
+ begin
RTLeventWaitFor(FNotifyStartTask,500);
if not FDone then
begin
@@ -3344,9 +3409,15 @@ begin
try
FBuildEngine.Compile(APackage);
FCompilationOK:=true;
+ FBuildEngine.log(vlInfo,'Done compiling: '+APackage.Name);
+ RaiseMainEvent;
except
on E: Exception do
- FErrorMessage := E.Message;
+ begin
+ FErrorMessage := 'Failed compiling: '+APackage.Name+': '+E.Message;
+ FBuildEngine.log(vlInfo,FErrorMessage);
+ RaiseMainEvent;
+ end;
end;
end;
end;
@@ -5019,6 +5090,27 @@ begin
FCompilerVersion:={$I %FPCVERSION%};
{$endif HAS_UNIT_PROCESS}
end;
+ if (FSourceOS=osNone) then
+ begin
+{$ifdef HAS_UNIT_PROCESS}
+ // Detect compiler version/target from -i option
+ infosl:=TStringList.Create;
+ infosl.Delimiter:=' ';
+ infosl.DelimitedText:=GetCompilerInfo(GetCompiler,'-iDWSPSO', False, True);
+ if infosl.Count<>4 then
+ Raise EInstallerError.Create(SErrInvalidFPCInfo);
+ FCompilerDate:=infosl[0];
+ FFullCompilerVersion:=infosl[1];
+ FSourceCPU:=StringToCPU(infosl[2]);
+ FSourceOS:=StringToOS(infosl[3]);
+{$else HAS_UNIT_PROCESS}
+ // Defaults taken from compiler used to build fpmake
+ FSourceCPU:=StringToCPU({$I %FPCTARGETCPU%});
+ FSourceOS:=StringToOS({$I %FPCTARGETOS%});
+ FFullCompilerVersion:={$I %FPCFULLVERSION%};
+ FCompilerDate:={$I %FPCDATE%};
+{$endif HAS_UNIT_PROCESS}
+ end;
end;
diff --git a/avx512-0037785/packages/fv/src/views.pas b/avx512-0037785/packages/fv/src/views.pas
index cd85455f0c..7a44ccec42 100644
--- a/avx512-0037785/packages/fv/src/views.pas
+++ b/avx512-0037785/packages/fv/src/views.pas
@@ -1905,7 +1905,8 @@ VAR S, D: Sw_Integer; Min, Max: TPoint;
PROCEDURE GrowI (Var I: Sw_Integer);
BEGIN
If (GrowMode AND gfGrowRel = 0) Then Inc(I, D)
- Else I := (I * S + (S - D) SHR 1) DIV (S - D); { Calc grow value }
+ Else If S = D then I := 1
+ Else I := (I * S + (S - D) SHR 1) DIV (S - D); { Calc grow value }
END;
BEGIN
diff --git a/avx512-0037785/packages/pasjpeg/examples/demo.lpi b/avx512-0037785/packages/pasjpeg/examples/demo.lpi
new file mode 100644
index 0000000000..99fac0cd7f
--- /dev/null
+++ b/avx512-0037785/packages/pasjpeg/examples/demo.lpi
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+ <ProjectOptions>
+ <Version Value="12"/>
+ <General>
+ <Flags>
+ <MainUnitHasCreateFormStatements Value="False"/>
+ <MainUnitHasTitleStatement Value="False"/>
+ <MainUnitHasScaledStatement Value="False"/>
+ <UseDefaultCompilerOptions Value="True"/>
+ </Flags>
+ <SessionStorage Value="InProjectDir"/>
+ <Title Value="demo"/>
+ <UseAppBundle Value="False"/>
+ <ResourceType Value="res"/>
+ </General>
+ <BuildModes>
+ <Item Name="Default" Default="True"/>
+ </BuildModes>
+ <PublishOptions>
+ <Version Value="2"/>
+ <UseFileFilters Value="True"/>
+ </PublishOptions>
+ <RunParams>
+ <FormatVersion Value="2"/>
+ </RunParams>
+ <Units>
+ <Unit>
+ <Filename Value="demo.pas"/>
+ <IsPartOfProject Value="True"/>
+ <UnitName Value="Demo"/>
+ </Unit>
+ </Units>
+ </ProjectOptions>
+ <CompilerOptions>
+ <Version Value="11"/>
+ <Target>
+ <Filename Value="demo"/>
+ </Target>
+ <SearchPaths>
+ <IncludeFiles Value="$(ProjOutDir)"/>
+ <OtherUnitFiles Value="../src"/>
+ <UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
+ </SearchPaths>
+ </CompilerOptions>
+ <Debugging>
+ <Exceptions>
+ <Item>
+ <Name Value="ECompilerAbort"/>
+ </Item>
+ </Exceptions>
+ </Debugging>
+</CONFIG>
diff --git a/avx512-0037785/packages/pasjpeg/examples/example.pas b/avx512-0037785/packages/pasjpeg/examples/example.pas
index 5362912c8c..a4f052883b 100644
--- a/avx512-0037785/packages/pasjpeg/examples/example.pas
+++ b/avx512-0037785/packages/pasjpeg/examples/example.pas
@@ -1,3 +1,8 @@
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$GOTO ON}
+{$DEFINE DELPHI_STREAM}
+{$ENDIF}
Unit example;
{ This file illustrates how to use the IJG code as a subroutine library
@@ -37,6 +42,10 @@ function read_JPEG_file (filename : string) : boolean;
implementation
+{$ifdef delphi_stream}
+ uses
+ Classes;
+{$endif delphi_stream}
{ <setjmp.h> is used for the optional error recovery mechanism shown in
the second part of the example. }
@@ -93,7 +102,11 @@ var
jerr : jpeg_error_mgr;
{ More stuff }
+{$ifdef delphi_stream}
+ outfile : TFileStream;
+{$else delphi_stream}
outfile : FILE; { target file }
+{$endif delphi_stream}
row_pointer : array[0..0] of JSAMPROW ; { pointer to JSAMPLE row[s] }
row_stride : int; { physical row width in image buffer }
begin
@@ -117,7 +130,9 @@ begin
stdio stream. You can also write your own code to do something else.
VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
requires it in order to write binary files. }
-
+{$ifdef delphi_stream}
+ outfile := TFileStream.Create(filename, fmCreate);
+{$else delphi_stream}
Assign(outfile, filename);
{$push}{$I-}
ReWrite(outfile, 1);
@@ -127,6 +142,7 @@ begin
WriteLn(output, 'can''t open ', filename);
Halt(1);
end;
+{$endif delphi_stream}
jpeg_stdio_dest(@cinfo, @outfile);
{ Step 3: set parameters for compression }
@@ -179,7 +195,11 @@ begin
jpeg_finish_compress(@cinfo);
{ After finish_compress, we can close the output file. }
+{$ifdef delphi_stream}
+ outfile.Free;
+{$else delphi_stream}
system.close(outfile);
+{$endif delphi_stream}
{ Step 7: release JPEG compression object }
@@ -321,7 +341,11 @@ var
jerr : my_error_mgr;
{ More stuff }
- infile : FILE; { source file }
+{$ifdef delphi_stream}
+ infile : TFileStream;
+{$else delphi_stream}
+ infile : FILE; { target file }
+{$endif delphi_stream}
buffer : JSAMPARRAY; { Output row buffer }
row_stride : int; { physical row width in output buffer }
begin
@@ -331,6 +355,9 @@ begin
VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
requires it in order to read binary files. }
+{$ifdef delphi_stream}
+ infile := TFileStream.Create(filename, fmOpenRead);
+{$else delphi_stream}
Assign(infile, filename);
{$push}{$I-}
Reset(infile, 1);
@@ -341,6 +368,7 @@ begin
read_JPEG_file := FALSE;
exit;
end;
+{$endif delphi_stream}
{ Step 1: allocate and initialize JPEG decompression object }
@@ -356,7 +384,11 @@ begin
{ Nomssi: if we get here, we are in trouble, because e.g. cinfo.mem
is not guaranted to be NIL }
jpeg_destroy_decompress(@cinfo);
+{$ifdef delphi_stream}
+ infile.Free;
+{$else delphi_stream}
system.close(infile);
+{$endif delphi_stream}
read_JPEG_file := FALSE;
exit;
end;
@@ -440,7 +472,11 @@ begin
Here we postpone it until after no more JPEG errors are possible,
so as to simplify the setjmp error logic above. (Actually, I don't
think that jpeg_destroy can do an error exit, but why assume anything...) }
+{$ifdef delphi_stream}
+ infile.Free;
+{$else delphi_stream}
system.close(infile);
+{$endif delphi_stream}
{ At this point you may want to check to see whether any corrupt-data
warnings occurred (test whether jerr.pub.num_warnings is nonzero). }
diff --git a/avx512-0037785/packages/pastojs/src/fppas2js.pp b/avx512-0037785/packages/pastojs/src/fppas2js.pp
index 7d5d6756a7..f60b74be61 100644
--- a/avx512-0037785/packages/pastojs/src/fppas2js.pp
+++ b/avx512-0037785/packages/pastojs/src/fppas2js.pp
@@ -506,6 +506,7 @@ const
nDuplicateMessageIdXAtY = 4029;
nDispatchRequiresX = 4030;
nConstRefNotForXAsConst = 4031;
+ nSymbolCannotBeExportedFromALibrary = 4032;
// resourcestring patterns of messages
resourcestring
sPasElementNotSupported = 'Pascal element not supported: %s';
@@ -539,6 +540,7 @@ resourcestring
sDuplicateMessageIdXAtY = 'Duplicate message id "%s" at %s';
sDispatchRequiresX = 'Dispatch requires %s';
sConstRefNotForXAsConst = 'ConstRef not yet implemented for %s. Treating as Const';
+ sSymbolCannotBeExportedFromALibrary = 'The symbol cannot be exported from a library';
const
ExtClassBracketAccessor = '[]'; // external name '[]' marks the array param getter/setter
@@ -606,6 +608,7 @@ type
pbifnValEnum,
pbifnFreeLocalVar,
pbifnFreeVar,
+ pbifnLibraryMain,
pbifnOverflowCheckInt,
pbifnProcType_Create,
pbifnProcType_CreateSafe,
@@ -671,6 +674,7 @@ type
pbivnImplCode,
pbivnMessageInt,
pbivnMessageStr,
+ pbivnLibrary, // library
pbivnLocalModuleRef,
pbivnLocalProcRef,
pbivnLocalTypeRef,
@@ -682,6 +686,7 @@ type
pbivnPtrClass,
pbivnPtrRecord,
pbivnProcOk,
+ pbivnProgram, // program
pbivnResourceStrings,
pbivnResourceStringOrig,
pbivnRTL,
@@ -791,6 +796,7 @@ const
'valEnum', // pbifnValEnum rtl.valEnum
'freeLoc', // pbifnFreeLocalVar rtl.freeLoc
'free', // pbifnFreeVar rtl.free
+ '$main', // pbifnLibraryMain
'oc', // pbifnOverflowCheckInt rtl.oc
'createCallback', // pbifnProcType_Create rtl.createCallback
'createSafeCallback', // pbifnProcType_CreateSafe rtl.createSafeCallback
@@ -855,6 +861,7 @@ const
'$implcode', // pbivnImplCode
'$msgint', // pbivnMessageInt
'$msgstr', // pbivnMessageStr
+ 'library', // pbivnLibrary pas.library
'$lm', // pbivnLocalModuleRef
'$lp', // pbivnLocalProcRef
'$lt', // pbivnLocalTypeRef
@@ -866,6 +873,7 @@ const
'$class', // pbivnPtrClass, ClassType
'$record', // pbivnPtrRecord, hidden recordtype
'$ok', // pbivnProcOk
+ 'program', // pbivnProgram pas.program
'$resourcestrings', // pbivnResourceStrings
'org', // pbivnResourceStringOrig
'rtl', // pbivnRTL
@@ -1538,6 +1546,7 @@ type
Params: TParamsExpr); override;
procedure FinishPropertyParamAccess(Params: TParamsExpr; Prop: TPasProperty
); override;
+ procedure FinishExportSymbol(El: TPasExportSymbol); override;
procedure FindCreatorArrayOfConst(Args: TFPList; ErrorEl: TPasElement);
function FindProc_ArrLitToArrayOfConst(ErrorEl: TPasElement): TPasFunction; virtual;
function FindSystemExternalClassType(const aClassName, JSName: string;
@@ -2071,7 +2080,7 @@ type
Procedure CreateInitSection(El: TPasModule; Src: TJSSourceElements; AContext: TConvertContext); virtual;
Procedure AddHeaderStatement(JS: TJSElement; PosEl: TPasElement; aContext: TConvertContext); virtual;
Procedure AddImplHeaderStatement(JS: TJSElement; PosEl: TPasElement; aContext: TConvertContext); virtual;
- Procedure AddDelayedInits(El: TPasProgram; Src: TJSSourceElements; AContext: TConvertContext); virtual;
+ Procedure AddDelayedInits(El: TPasModule; Src: TJSSourceElements; AContext: TConvertContext); virtual;
Procedure AddDelaySpecializeInit(El: TPasGenericType; Src: TJSSourceElements; AContext: TConvertContext); virtual;
// enum and sets
Function CreateReferencedSet(El: TPasElement; SetExpr: TJSElement): TJSElement; virtual;
@@ -3945,6 +3954,7 @@ var
begin
Lines:=El.Tokens;
if Lines=nil then exit;
+ // ToDo: resolve explicit references
end;
procedure TPas2JSResolver.ResolveNameExpr(El: TPasExpr; const aName: string;
@@ -4880,6 +4890,41 @@ begin
FindCreatorArrayOfConst(Args,Params);
end;
+procedure TPas2JSResolver.FinishExportSymbol(El: TPasExportSymbol);
+var
+ ResolvedEl: TPasResolverResult;
+ DeclEl: TPasElement;
+ Proc: TPasProcedure;
+begin
+ if El.Parent is TLibrarySection then
+ // ok
+ else
+ // everywhere else: not supported
+ RaiseMsg(20210106224720,nNotSupportedX,sNotSupportedX,['non library export'],El.ExportIndex);
+ if El.ExportIndex<>nil then
+ RaiseMsg(20210106223403,nNotSupportedX,sNotSupportedX,['export index'],El.ExportIndex);
+
+ inherited FinishExportSymbol(El);
+
+ ComputeElement(El,ResolvedEl,[]);
+ DeclEl:=ResolvedEl.IdentEl;
+ if DeclEl=nil then
+ RaiseMsg(20210106223620,nSymbolCannotBeExportedFromALibrary,
+ sSymbolCannotBeExportedFromALibrary,[],El)
+ else if DeclEl is TPasProcedure then
+ begin
+ Proc:=TPasProcedure(DeclEl);
+ if Proc.Parent is TPasSection then
+ // ok
+ else
+ RaiseMsg(20210106224436,nSymbolCannotBeExportedFromALibrary,
+ sSymbolCannotBeExportedFromALibrary,[],El);
+ end
+ else
+ RaiseMsg(20210106223621,nSymbolCannotBeExportedFromALibrary,
+ sSymbolCannotBeExportedFromALibrary,[],El);
+end;
+
procedure TPas2JSResolver.FindCreatorArrayOfConst(Args: TFPList;
ErrorEl: TPasElement);
var
@@ -8083,6 +8128,18 @@ Program:
};
});
+Library:
+ rtl.module('library',
+ [<uses1>,<uses2>, ...],
+ function(){
+ var $mod = this;
+ <librarysection>
+ this.$main=function(){
+ <initialization>
+ };
+ });
+ export1 = pas.unit1.func1;
+
Unit without implementation:
rtl.module('<unitname>',
[<interface uses1>,<uses2>, ...],
@@ -8136,6 +8193,7 @@ begin
ModScope:=nil;
OuterSrc:=TJSSourceElements(CreateElement(TJSSourceElements, El));
Result:=OuterSrc;
+ IntfContext:=nil;
ok:=false;
try
// create 'rtl.module(...)'
@@ -8145,7 +8203,7 @@ begin
ArgArray := RegModuleCall.Args;
RegModuleCall.Args:=ArgArray;
- // add unitname parameter: unitname
+ // add module name parameter
ModuleName:=TransformModuleName(El,false,AContext);
ArgArray.Elements.AddElement.Expr:=CreateLiteralString(El,ModuleName);
@@ -8183,95 +8241,88 @@ begin
IntfContext:=TInterfaceSectionContext.Create(El,Src,AContext)
else
IntfContext:=TSectionContext.Create(El,Src,AContext);
- try
- // add "var $mod = this;"
- IntfContext.ThisVar.Element:=El;
- IntfContext.ThisVar.Kind:=cvkGlobal;
- if El.CustomData is TPasModuleScope then
- IntfContext.ScannerBoolSwitches:=TPasModuleScope(El.CustomData).BoolSwitches;
- ModVarName:=GetBIName(pbivnModule);
- IntfContext.AddLocalVar(ModVarName,El,cvkGlobal,false);
- AddToSourceElements(Src,CreateVarStatement(ModVarName,
- CreatePrimitiveDotExpr('this',El),El));
-
- if (ModScope<>nil) then
- RestoreImplJSLocals(ModScope,IntfContext);
-
- if (El is TPasProgram) then
- begin // program
- Prg:=TPasProgram(El);
- if Assigned(Prg.ProgramSection) then
- AddToSourceElements(Src,ConvertDeclarations(Prg.ProgramSection,IntfContext));
- AddDelayedInits(Prg,Src,IntfContext);
- CreateInitSection(Prg,Src,IntfContext);
- end
- else if El is TPasLibrary then
- begin // library
- Lib:=TPasLibrary(El);
- if Assigned(Lib.LibrarySection) then
- AddToSourceElements(Src,ConvertDeclarations(Lib.LibrarySection,IntfContext));
- // ToDo AddDelayedInits(Lib,Src,IntfContext);
- CreateInitSection(Lib,Src,IntfContext);
- end
- else
- begin // unit
- IntfSecCtx:=TInterfaceSectionContext(IntfContext);
- if Assigned(El.ImplementationSection) then
- begin
- // add var $impl = $mod.$impl
- ImplVarSt:=CreateVarStatement(GetBIName(pbivnImplementation),
- CreateMemberExpression([ModVarName,GetBIName(pbivnImplementation)]),El);
- AddToSourceElements(Src,ImplVarSt);
- // register local var $impl
- IntfSecCtx.AddLocalVar(GetBIName(pbivnImplementation),El.ImplementationSection,cvkGlobal,false);
- end;
- if Assigned(El.InterfaceSection) then
- AddToSourceElements(Src,ConvertDeclarations(El.InterfaceSection,IntfSecCtx));
+ // add "var $mod = this;"
+ IntfContext.ThisVar.Element:=El;
+ IntfContext.ThisVar.Kind:=cvkGlobal;
+ if El.CustomData is TPasModuleScope then
+ IntfContext.ScannerBoolSwitches:=TPasModuleScope(El.CustomData).BoolSwitches;
+ ModVarName:=GetBIName(pbivnModule);
+ IntfContext.AddLocalVar(ModVarName,El,cvkGlobal,false);
+ AddToSourceElements(Src,CreateVarStatement(ModVarName,
+ CreatePrimitiveDotExpr('this',El),El));
+
+ if (ModScope<>nil) then
+ RestoreImplJSLocals(ModScope,IntfContext);
- ImplFunc:=CreateImplementationSection(El,IntfSecCtx);
- // add $mod.$implcode = ImplFunc;
- AssignSt:=TJSSimpleAssignStatement(CreateElement(TJSSimpleAssignStatement,El));
- AssignSt.LHS:=CreateMemberExpression([ModVarName,GetBIName(pbivnImplCode)]);
- AssignSt.Expr:=ImplFunc;
- AddToSourceElements(Src,AssignSt);
-
- // append initialization section
- CreateInitSection(El,Src,IntfSecCtx);
+ if (El is TPasProgram) then
+ begin // program
+ Prg:=TPasProgram(El);
+ if Assigned(Prg.ProgramSection) then
+ AddToSourceElements(Src,ConvertDeclarations(Prg.ProgramSection,IntfContext));
+ AddDelayedInits(Prg,Src,IntfContext);
+ CreateInitSection(Prg,Src,IntfContext);
+ end
+ else if El is TPasLibrary then
+ begin // library
+ Lib:=TPasLibrary(El);
+ if Assigned(Lib.LibrarySection) then
+ AddToSourceElements(Src,ConvertDeclarations(Lib.LibrarySection,IntfContext));
+ AddDelayedInits(Lib,Src,IntfContext);
+ CreateInitSection(Lib,Src,IntfContext);
+ // ToDo: append exports
+ end
+ else
+ begin // unit
+ IntfSecCtx:=TInterfaceSectionContext(IntfContext);
+ if Assigned(El.ImplementationSection) then
+ begin
+ // add var $impl = $mod.$impl
+ ImplVarSt:=CreateVarStatement(GetBIName(pbivnImplementation),
+ CreateMemberExpression([ModVarName,GetBIName(pbivnImplementation)]),El);
+ AddToSourceElements(Src,ImplVarSt);
+ // register local var $impl
+ IntfSecCtx.AddLocalVar(GetBIName(pbivnImplementation),El.ImplementationSection,cvkGlobal,false);
+ end;
+ if Assigned(El.InterfaceSection) then
+ AddToSourceElements(Src,ConvertDeclarations(El.InterfaceSection,IntfSecCtx));
+
+ ImplFunc:=CreateImplementationSection(El,IntfSecCtx);
+ // add $mod.$implcode = ImplFunc;
+ AssignSt:=TJSSimpleAssignStatement(CreateElement(TJSSimpleAssignStatement,El));
+ AssignSt.LHS:=CreateMemberExpression([ModVarName,GetBIName(pbivnImplCode)]);
+ AssignSt.Expr:=ImplFunc;
+ AddToSourceElements(Src,AssignSt);
- if TJSSourceElements(ImplFunc.AFunction.Body.A).Statements.Count=0 then
- begin
- // empty implementation
-
- // remove unneeded $impl from interface
- RemoveFromSourceElements(Src,ImplVarSt);
- // remove unneeded $mod.$implcode = function(){}
- RemoveFromSourceElements(Src,AssignSt);
- HasImplUsesClause:=(El.ImplementationSection<>nil)
- and (length(El.ImplementationSection.UsesClause)>0);
- end
- else
- begin
- HasImplUsesClause:=true;
- end;
+ // append initialization section
+ CreateInitSection(El,Src,IntfSecCtx);
- if HasImplUsesClause then
- // add implementation uses list: [<implementation uses1>,<uses2>, ...]
- ArgArray.AddElement(CreateUsesList(El.ImplementationSection,AContext));
+ if TJSSourceElements(ImplFunc.AFunction.Body.A).Statements.Count=0 then
+ begin
+ // empty implementation
+ // remove unneeded $impl from interface
+ RemoveFromSourceElements(Src,ImplVarSt);
+ // remove unneeded $mod.$implcode = function(){}
+ RemoveFromSourceElements(Src,AssignSt);
+ HasImplUsesClause:=(El.ImplementationSection<>nil)
+ and (length(El.ImplementationSection.UsesClause)>0);
+ end
+ else
+ begin
+ HasImplUsesClause:=true;
end;
- if (ModScope<>nil) and (coStoreImplJS in Options) then
- StoreImplJSLocals(ModScope,IntfContext);
- finally
- IntfContext.Free;
- end;
+ if HasImplUsesClause then
+ // add implementation uses list: [<implementation uses1>,<uses2>, ...]
+ ArgArray.AddElement(CreateUsesList(El.ImplementationSection,AContext));
- // add implementation function
- if ImplVarSt<>nil then
- begin
- end;
+ end; // end unit
+
+ if (ModScope<>nil) and (coStoreImplJS in Options) then
+ StoreImplJSLocals(ModScope,IntfContext);
ok:=true;
finally
+ IntfContext.Free;
if not ok then
FreeAndNil(Result);
end;
@@ -13348,6 +13399,15 @@ begin
Result:=Add;
exit;
end
+ else if bt in btAllJSInteger then
+ begin
+ // ord(integer)
+ Result:=CheckOrdConstant(aResolver,Param);
+ if Result<>nil then exit;
+ // ord(integer) -> integer
+ Result:=ConvertExpression(Param,AContext);
+ exit;
+ end
else if bt=btContext then
begin
C:=ParamResolved.LoTypeEl.ClassType;
@@ -15397,6 +15457,8 @@ begin
end
else if C=TPasAttributes then
continue
+ else if C=TPasExportSymbol then
+ continue
else
RaiseNotSupported(P as TPasElement,AContext,20161024191434);
Add(E,P);
@@ -17148,11 +17210,21 @@ begin
Scope:=nil;
end;
- IsMain:=(El is TPasProgram);
- if IsMain then
+ if El.ClassType=TPasProgram then
+ begin
+ IsMain:=true;
FunName:=GetBIName(pbifnProgramMain)
+ end
+ else if El.ClassType=TPasLibrary then
+ begin
+ IsMain:=true;
+ FunName:=GetBIName(pbifnLibraryMain)
+ end
else
+ begin
+ IsMain:=false;
FunName:=GetBIName(pbifnUnitInit);
+ end;
NeedRTLCheckVersion:=IsMain and (coRTLVersionCheckMain in Options);
RootContext:=AContext.GetRootContext as TRootContext;
@@ -17489,6 +17561,7 @@ var
L: TJSLiteral;
AsmLines: TStrings;
Line, Col, StartLine: integer;
+ Statements: TJSStatementList;
begin
if AContext=nil then ;
AsmLines:=El.Tokens;
@@ -17507,6 +17580,15 @@ begin
L:=TJSLiteral.Create(Line+StartLine,Col,El.SourceFilename);
L.Value.CustomValue:=TJSString(s);
Result:=L;
+ if Pos(';',s)>0 then
+ begin
+ // multi statement JS
+ // for example "if e then asm a;b end;"
+ // -> if (e){ a;b }
+ Statements:=TJSStatementList.Create(L.Line,L.Column,L.Source);
+ Statements.A:=L;
+ Result:=Statements;
+ end;
end;
end;
@@ -17680,7 +17762,7 @@ begin
IntfSec.AddImplHeaderStatement(JS);
end;
-procedure TPasToJSConverter.AddDelayedInits(El: TPasProgram;
+procedure TPasToJSConverter.AddDelayedInits(El: TPasModule;
Src: TJSSourceElements; AContext: TConvertContext);
var
aResolver: TPas2JSResolver;
@@ -26397,13 +26479,7 @@ begin
or (C=TPasClassDestructor) then
AddGlobalClassMethod(FuncContext,TPasProcedure(P))
else
- begin
Methods.Add(P);
- if (C=TPasConstructor)
- or ((aResolver<>nil) and aResolver.IsClassMethod(P)
- and not aResolver.MethodIsStatic(TPasProcedure(P))) then
- IsComplex:=true; // needs $record
- end;
end
else if C=TPasAttributes then
else
@@ -26617,8 +26693,10 @@ begin
if Result<>'' then
exit;
end;
- if El is TPasProgram then
- Result:='program'
+ if El.ClassType=TPasProgram then
+ Result:=GetBIName(pbivnProgram)
+ else if El.ClassType=TPasLibrary then
+ Result:=GetBIName(pbivnLibrary)
else
begin
Result:='';
diff --git a/avx512-0037785/packages/pastojs/src/pas2jsfiler.pp b/avx512-0037785/packages/pastojs/src/pas2jsfiler.pp
index 3767d01d2c..4a28a96f78 100644
--- a/avx512-0037785/packages/pastojs/src/pas2jsfiler.pp
+++ b/avx512-0037785/packages/pastojs/src/pas2jsfiler.pp
@@ -609,6 +609,7 @@ type
public
Owner: TObject;
end;
+ EPas2JsFilerErrorClass = class of EPas2JsFilerError;
EPas2JsWriteError = class(EPas2JsFilerError);
EPas2JsReadError = class(EPas2JsFilerError);
@@ -665,6 +666,7 @@ type
TPCUFiler = class
private
+ FErrorClass: EPas2JsFilerErrorClass;
FFileVersion: longint;
FGUID: TGUID;
FInitialFlags: TPCUInitialFlags;
@@ -676,7 +678,7 @@ type
function GetSourceFiles(Index: integer): TPCUSourceFile;
protected
FElementRefs: TAVLTree; // tree of TPCUFilerElementRef sorted for Element
- procedure RaiseMsg(Id: int64; const Msg: string = ''); virtual; abstract; overload;
+ procedure RaiseMsg(Id: int64; const Msg: string = ''); virtual; overload;
procedure RaiseMsg(Id: int64; El: TPasElement; const Msg: string = ''); overload;
function GetDefaultMemberVisibility(El: TPasElement): TPasMemberVisibility; virtual;
function GetDefaultPasScopeVisibilityContext(Scope: TPasScope): TPasElement; virtual;
@@ -703,6 +705,7 @@ type
property SourceFiles[Index: integer]: TPCUSourceFile read GetSourceFiles;
property ElementRefs: TAVLTree read FElementRefs;
property GUID: TGUID read FGUID write FGUID;
+ property ErrorClass: EPas2JsFilerErrorClass read FErrorClass write FErrorClass;
end;
{ TPCUCustomWriter }
@@ -711,6 +714,7 @@ type
private
FOnIsElementUsed: TPas2JSIsElementUsedEvent;
public
+ constructor Create; override;
procedure WritePCU(aResolver: TPas2JSResolver; aConverter: TPasToJSConverter;
InitFlags: TPCUInitialFlags; aStream: TStream; Compressed: boolean); virtual; abstract;
property OnIsElementUsed: TPas2JSIsElementUsedEvent read FOnIsElementUsed write FOnIsElementUsed;
@@ -721,12 +725,15 @@ type
TPCUCustomReader = class(TPCUFiler)
private
+ FPCUFilename: string;
FSourceFilename: string;
public
+ constructor Create; override;
procedure ReadPCU(aResolver: TPas2JSResolver; aStream: TStream); virtual; abstract;
function ReadContinue: boolean; virtual; abstract; // true=finished
function ReadCanContinue: boolean; virtual; // true=not finished and no pending used interface
property SourceFilename: string read FSourceFilename write FSourceFilename; // default value for TPasElement.SourceFilename
+ property PCUFilename: string read FPCUFilename write FPCUFilename; // for nicer error messages
end;
TPCUReaderClass = class of TPCUCustomReader;
@@ -768,7 +775,6 @@ type
FBuiltInSymbolsArr: TJSONArray;
protected
FFirstNewExt, FLastNewExt: TPCUFilerElementRef; // not yet stored external references
- procedure RaiseMsg(Id: int64; const Msg: string = ''); override; overload;
procedure ResolvePendingElRefs(Ref: TPCUFilerElementRef);
function CheckElScope(El: TPasElement; NotNilId: int64; ScopeClass: TPasScopeClass): TPasScope; virtual;
procedure AddArrayFlag(Obj: TJSONObject; var Arr: TJSONArray;
@@ -1239,6 +1245,7 @@ type
procedure ReadPCU(aResolver: TPas2JSResolver; aStream: TStream); override; // sets property JSON, reads header and returns
procedure ReadJSONHeader(aResolver: TPas2JSResolver; Obj: TJSONObject); virtual;
function ReadContinue: boolean; override; // true=finished
+ function GetPCUExt: string; virtual; // without dot
property FileVersion: longint read FFileVersion;
property JSON: TJSONObject read FJSON;
end;
@@ -1857,6 +1864,14 @@ begin
AddLine(Line);
end;
+{ TPCUCustomWriter }
+
+constructor TPCUCustomWriter.Create;
+begin
+ inherited Create;
+ FErrorClass:=EPas2JsWriteError;
+end;
+
{ TPCUReaderPendingSpecialized }
destructor TPCUReaderPendingSpecialized.Destroy;
@@ -1877,6 +1892,12 @@ end;
{ TPCUCustomReader }
+constructor TPCUCustomReader.Create;
+begin
+ inherited Create;
+ FErrorClass:=EPas2JsReadError;
+end;
+
function TPCUCustomReader.ReadCanContinue: boolean;
var
Module: TPasModule;
@@ -1930,6 +1951,18 @@ begin
Result:=TPCUSourceFile(FSourceFiles[Index]);
end;
+procedure TPCUFiler.RaiseMsg(Id: int64; const Msg: string);
+var
+ E: EPas2JsFilerError;
+begin
+ E:=ErrorClass.Create('['+IntToStr(Id)+'] '+Msg);
+ E.Owner:=Self;
+ {$IFDEF VerbosePCUFiler}
+ writeln(ClassName+'/TPCUFiler.RaiseMsg ',E.Message);
+ {$ENDIF}
+ raise E;
+end;
+
procedure TPCUFiler.RaiseMsg(Id: int64; El: TPasElement; const Msg: string);
var
Path, s: String;
@@ -2215,18 +2248,6 @@ begin
end;
end;
-procedure TPCUWriter.RaiseMsg(Id: int64; const Msg: string);
-var
- E: EPas2JsWriteError;
-begin
- E:=EPas2JsWriteError.Create('['+IntToStr(Id)+'] '+Msg);
- E.Owner:=Self;
- {$IFDEF VerbosePCUFiler}
- writeln('TPCUWriter.RaiseMsg ',E.Message);
- {$ENDIF}
- raise E;
-end;
-
function TPCUWriter.CheckElScope(El: TPasElement; NotNilId: int64;
ScopeClass: TPasScopeClass): TPasScope;
var
@@ -5781,12 +5802,16 @@ end;
procedure TPCUReader.RaiseMsg(Id: int64; const Msg: string);
var
- E: EPas2JsReadError;
+ E: EPas2JsFilerError;
+ s: String;
begin
- E:=EPas2JsReadError.Create('['+IntToStr(Id)+'] '+Msg);
+ s:='['+IntToStr(Id)+'] '+Msg;
+ if PCUFilename<>'' then
+ s:=s+' file: '+PCUFilename;
+ E:=ErrorClass.Create(s);
E.Owner:=Self;
{$IFDEF VerbosePCUFiler}
- writeln('TPCUReader.RaiseMsg ',E.Message);
+ writeln(ClassName+'/TPCUReader.RaiseMsg ',E.Message);
{$ENDIF}
raise E;
end;
@@ -6317,9 +6342,9 @@ begin
writeln('TPCUReader.ReadHeaderVersion ',FFileVersion);
{$ENDIF}
if FFileVersion<1 then
- RaiseMsg(20180130201801,'invalid PCU file version');
+ RaiseMsg(20180130201801,'invalid file version');
if FFileVersion>PCUVersion then
- RaiseMsg(20180130201822,'pcu file was created by a newer compiler.');
+ RaiseMsg(20180130201822,'file was created by a newer compiler.');
end;
procedure TPCUReader.ReadGUID(Obj: TJSONObject);
@@ -10135,6 +10160,15 @@ begin
{$ENDIF}
end;
+function TPCUReader.GetPCUExt: string;
+begin
+ Result:=ExtractFileExt(PCUFilename);
+ if Result='' then
+ Result:='pcu'
+ else
+ System.Delete(Result,1,1); // remove leading dot
+end;
+
{ TPas2JSPrecompileFormats }
function TPas2JSPrecompileFormats.GetItems(Index: integer
diff --git a/avx512-0037785/packages/pastojs/src/pas2jspcucompiler.pp b/avx512-0037785/packages/pastojs/src/pas2jspcucompiler.pp
index 5baf59da7a..ec9eedc432 100644
--- a/avx512-0037785/packages/pastojs/src/pas2jspcucompiler.pp
+++ b/avx512-0037785/packages/pastojs/src/pas2jspcucompiler.pp
@@ -187,6 +187,7 @@ begin
RaiseInternalError(20180312142954,'');
FPCUReader:=FPCUFormat.ReaderClass.Create;
FPCUReader.SourceFilename:=ExtractFileName(MyFile.PCUFilename);
+ FPCUReader.PCUFilename:=MyFile.PCUFilename;
if MyFile.ShowDebug then
MyFile.Log.LogMsg(nParsingFile,[QuoteStr(MyFile.PCUFilename)]);
diff --git a/avx512-0037785/packages/pastojs/tests/tcmodules.pas b/avx512-0037785/packages/pastojs/tests/tcmodules.pas
index 1ab920c33a..ca46edd38b 100644
--- a/avx512-0037785/packages/pastojs/tests/tcmodules.pas
+++ b/avx512-0037785/packages/pastojs/tests/tcmodules.pas
@@ -125,6 +125,7 @@ type
FModules: TObjectList;// list of TTestEnginePasResolver
FParser: TTestPasParser;
FPasProgram: TPasProgram;
+ FPasLibrary: TPasLibrary;
FHintMsgs: TObjectList; // list of TTestHintMessage
FHintMsgsGood: TFPList; // list of TTestHintMessage marked as expected
FJSRegModuleCall: TJSCallExpression;
@@ -157,6 +158,7 @@ type
procedure ParseModuleQueue; virtual;
procedure ParseModule; virtual;
procedure ParseProgram; virtual;
+ procedure ParseLibrary; virtual;
procedure ParseUnit; virtual;
protected
function FindModuleWithFilename(aFilename: string): TTestEnginePasResolver; virtual;
@@ -166,9 +168,11 @@ type
ImplementationSrc: string): TTestEnginePasResolver; virtual;
procedure AddSystemUnit(Parts: TSystemUnitParts = []); virtual;
procedure StartProgram(NeedSystemUnit: boolean; SystemUnitParts: TSystemUnitParts = []); virtual;
+ procedure StartLibrary(NeedSystemUnit: boolean; SystemUnitParts: TSystemUnitParts = []); virtual;
procedure StartUnit(NeedSystemUnit: boolean; SystemUnitParts: TSystemUnitParts = []); virtual;
procedure ConvertModule; virtual;
procedure ConvertProgram; virtual;
+ procedure ConvertLibrary; virtual;
procedure ConvertUnit; virtual;
function ConvertJSModuleToString(El: TJSElement): string; virtual;
procedure CheckDottedIdentifier(Msg: string; El: TJSElement; DottedName: string);
@@ -196,6 +200,7 @@ type
function GetResolver(const Filename: string): TTestEnginePasResolver;
function GetDefaultNamespace: string;
property PasProgram: TPasProgram Read FPasProgram;
+ property PasLibrary: TPasLibrary Read FPasLibrary;
property Resolvers[Index: integer]: TTestEnginePasResolver read GetResolvers;
property ResolverCount: integer read GetResolverCount;
property Engine: TTestEnginePasResolver read FEngine;
@@ -332,6 +337,7 @@ type
Procedure TestProc_External;
Procedure TestProc_ExternalOtherUnit;
Procedure TestProc_Asm;
+ Procedure TestProc_AsmSubBlock;
Procedure TestProc_Assembler;
Procedure TestProc_VarParam;
Procedure TestProc_VarParamString;
@@ -383,6 +389,7 @@ type
Procedure TestSet_Property;
Procedure TestSet_EnumConst;
Procedure TestSet_IntConst;
+ Procedure TestSet_IntRange;
Procedure TestSet_AnonymousEnumType;
Procedure TestSet_AnonymousEnumTypeChar; // ToDo
Procedure TestSet_ConstEnum;
@@ -894,6 +901,12 @@ type
Procedure TestAsync_Inherited;
Procedure TestAsync_ClassInterface;
Procedure TestAsync_ClassInterface_AsyncMissmatchFail;
+
+ // Library
+ Procedure TestLibrary_Empty;
+ Procedure TestLibrary_ExportFunc; // ToDo
+ // ToDo: test delayed specialization init
+ // ToDO: analyzer
end;
function LinesToStr(Args: array of const): string;
@@ -1587,6 +1600,22 @@ begin
FFirstPasStatement:=TPasImplBlock(PasProgram.InitializationSection.Elements[0]);
end;
+procedure TCustomTestModule.ParseLibrary;
+var
+ Init: TInitializationSection;
+begin
+ if SkipTests then exit;
+ ParseModule;
+ if SkipTests then exit;
+ AssertEquals('Has library',TPasLibrary,Module.ClassType);
+ FPasLibrary:=TPasLibrary(Module);
+ AssertNotNull('Has library section',PasLibrary.LibrarySection);
+ Init:=PasLibrary.InitializationSection;
+ if (Init<>nil) and (Init.Elements.Count>0) then
+ if TObject(Init.Elements[0]) is TPasImplBlock then
+ FFirstPasStatement:=TPasImplBlock(PasLibrary.InitializationSection.Elements[0]);
+end;
+
procedure TCustomTestModule.ParseUnit;
begin
if SkipTests then exit;
@@ -1869,6 +1898,17 @@ begin
Add('');
end;
+procedure TCustomTestModule.StartLibrary(NeedSystemUnit: boolean;
+ SystemUnitParts: TSystemUnitParts);
+begin
+ if NeedSystemUnit then
+ AddSystemUnit(SystemUnitParts)
+ else
+ Parser.ImplicitUses.Clear;
+ Add('library '+ExtractFileUnitName(Filename)+';');
+ Add('');
+end;
+
procedure TCustomTestModule.StartUnit(NeedSystemUnit: boolean;
SystemUnitParts: TSystemUnitParts);
begin
@@ -1974,6 +2014,8 @@ begin
AssertEquals('module name param is string',ord(jstString),ord(ModuleNameExpr.Value.ValueType));
if Module is TPasProgram then
AssertEquals('module name','program',String(ModuleNameExpr.Value.AsString))
+ else if Module is TPasLibrary then
+ AssertEquals('module name','library',String(ModuleNameExpr.Value.AsString))
else
AssertEquals('module name',Module.Name,String(ModuleNameExpr.Value.AsString));
@@ -1990,7 +2032,7 @@ begin
CheckFunctionParam('module intf-function',Arg,FJSModuleSrc);
// search for $mod.$init or $mod.$main - the last statement
- if Module is TPasProgram then
+ if (Module is TPasProgram) or (Module is TPasLibrary) then
begin
InitName:='$main';
AssertEquals('$mod.'+InitName+' function 1',true,JSModuleSrc.Statements.Count>0);
@@ -2009,7 +2051,7 @@ begin
InitFunction:=InitAssign.Expr as TJSFunctionDeclarationStatement;
FJSInitBody:=InitFunction.AFunction.Body as TJSFunctionBody;
end
- else if Module is TPasProgram then
+ else if (Module is TPasProgram) or (Module is TPasLibrary) then
CheckDottedIdentifier('init function',InitAssign.LHS,'$mod.'+InitName);
end;
end;
@@ -2028,6 +2070,13 @@ begin
ConvertModule;
end;
+procedure TCustomTestModule.ConvertLibrary;
+begin
+ Add('end.');
+ ParseLibrary;
+ ConvertModule;
+end;
+
procedure TCustomTestModule.ConvertUnit;
begin
Add('end.');
@@ -2089,7 +2138,7 @@ begin
// program main or unit initialization
if (Module is TPasProgram) or (Trim(InitStatements)<>'') then
begin
- if Module is TPasProgram then
+ if (Module is TPasProgram) or (Module is TPasLibrary) then
InitName:='$main'
else
InitName:='$init';
@@ -4092,6 +4141,65 @@ begin
]));
end;
+procedure TTestModule.TestProc_AsmSubBlock;
+begin
+ StartProgram(true,[supTObject]);
+ Add([
+ '{$mode delphi}',
+ 'type',
+ ' TBird = class end;',
+ 'procedure Run(w: word);',
+ 'begin;',
+ ' if true then asm console.log(); end;',
+ ' if w>3 then asm',
+ ' var a = w+1;',
+ ' w = a+3;',
+ ' end;',
+ ' while (w>7) do asm',
+ ' w+=3; w*=2;',
+ ' end;',
+ ' try',
+ ' except',
+ ' on E: TBird do',
+ ' asm console.log(E); end;',
+ ' on E: TObject do',
+ ' asm var i=3; i--; end;',
+ ' else asm Fly; High; end;',
+ ' end;',
+ 'end;',
+ 'begin']);
+ ConvertProgram;
+ CheckSource('TestProc_AsmSubBlock',
+ LinesToStr([ // statements
+ 'rtl.createClass(this, "TBird", pas.system.TObject, function () {',
+ '});',
+ 'this.Run = function (w) {',
+ ' if (true) console.log();',
+ ' if (w > 3) {',
+ ' var a = w+1;',
+ ' w = a+3;',
+ ' };',
+ ' while (w > 7) {',
+ ' w+=3; w*=2;',
+ ' };',
+ ' try {} catch ($e) {',
+ ' if ($mod.TBird.isPrototypeOf($e)) {',
+ ' var E = $e;',
+ ' console.log(E);',
+ ' } else if (pas.system.TObject.isPrototypeOf($e)) {',
+ ' var E = $e;',
+ ' var i=3; i--;',
+ ' } else {',
+ ' Fly; High;',
+ ' }',
+ ' };',
+ '};',
+ '']),
+ LinesToStr([
+ ''
+ ]));
+end;
+
procedure TTestModule.TestProc_Assembler;
begin
StartProgram(false);
@@ -6313,6 +6421,44 @@ begin
'']));
end;
+procedure TTestModule.TestSet_IntRange;
+begin
+ StartProgram(false);
+ Add([
+ 'type',
+ ' TRange = 1..3;',
+ ' TEnums = set of TRange;',
+ 'const',
+ ' Orange = 2;',
+ 'var',
+ ' Enum: byte;',
+ ' Enums: TEnums;',
+ 'begin',
+ ' Enums:=[];',
+ ' Enums:=[1];',
+ ' Enums:=[2..3];',
+ ' Include(enums,orange);',
+ ' Exclude(enums,orange);',
+ ' if orange in enums then;',
+ ' if orange in [orange,1] then;']);
+ ConvertProgram;
+ CheckSource('TestSet_IntRange',
+ LinesToStr([ // statements
+ 'this.Orange = 2;',
+ 'this.Enum = 0;',
+ 'this.Enums = {};',
+ '']),
+ LinesToStr([
+ '$mod.Enums = {};',
+ '$mod.Enums = rtl.createSet(1);',
+ '$mod.Enums = rtl.createSet(null, 2, 3);',
+ '$mod.Enums = rtl.includeSet($mod.Enums, 2);',
+ '$mod.Enums = rtl.excludeSet($mod.Enums, 2);',
+ 'if (2 in $mod.Enums) ;',
+ 'if (2 in rtl.createSet(2, 1)) ;',
+ '']));
+end;
+
procedure TTestModule.TestSet_AnonymousEnumType;
begin
StartProgram(false);
@@ -7075,7 +7221,9 @@ begin
'begin',
' i:=i2;',
' i:=default(TMyInt);',
- ' if i=i2 then ;']);
+ ' if i=i2 then ;',
+ ' i:=ord(i2);',
+ '']);
ConvertProgram;
CheckSource('TestIntegerRange',
LinesToStr([
@@ -7096,6 +7244,7 @@ begin
'$mod.i = $mod.i2;',
'$mod.i = -1;',
'if ($mod.i === $mod.i2) ;',
+ '$mod.i = $mod.i2;',
'']));
end;
@@ -7210,6 +7359,7 @@ begin
' i:=system.high(i);',
' i:=system.pred(i);',
' i:=system.succ(i);',
+ ' i:=system.ord(i);',
'']);
ConvertProgram;
CheckResolverUnexpectedHints;
@@ -7226,6 +7376,7 @@ begin
'$mod.i = 255;',
'$mod.i = $mod.i - 1;',
'$mod.i = $mod.i + 1;',
+ '$mod.i = $mod.i;',
'']));
end;
@@ -12292,12 +12443,20 @@ begin
'type',
' TPoint = record',
' x,y: longint;',
+ ' class procedure Run(w: longint = 13); static;',
' constructor Create(ax: longint; ay: longint = -1);',
' end;',
+ 'class procedure tpoint.run(w: longint);',
+ 'begin',
+ ' run;',
+ ' run();',
+ 'end;',
'constructor tpoint.create(ax,ay: longint);',
'begin',
' x:=ax;',
' self.y:=ay;',
+ ' run;',
+ ' run(ax);',
'end;',
'var r: TPoint;',
'begin',
@@ -12320,12 +12479,18 @@ begin
' this.y = s.y;',
' return this;',
' };',
+ ' this.Run = function (w) {',
+ ' $mod.TPoint.Run(13);',
+ ' $mod.TPoint.Run(13);',
+ ' };',
' this.Create = function (ax, ay) {',
' this.x = ax;',
' this.y = ay;',
+ ' this.Run(13);',
+ ' this.Run(ax);',
' return this;',
' };',
- '}, true);',
+ '});',
'this.r = this.TPoint.$new();',
'']),
LinesToStr([ // $mod.$main
@@ -23241,7 +23406,7 @@ begin
' $mod.THelper.$new("NewHlp", [3]);',
' return this;',
' };',
- '}, true);',
+ '});',
'rtl.createHelper(this, "THelper", null, function () {',
' this.NewHlp = function (w) {',
' this.Create(2);',
@@ -33110,6 +33275,42 @@ begin
ConvertProgram;
end;
+procedure TTestModule.TestLibrary_Empty;
+begin
+ StartLibrary(false);
+ Add([
+ '']);
+ ConvertLibrary;
+ CheckSource('TestLibrary_Empty',
+ LinesToStr([ // statements
+ '']),
+ LinesToStr([
+ '']));
+ CheckResolverUnexpectedHints();
+end;
+
+procedure TTestModule.TestLibrary_ExportFunc;
+begin
+ exit;
+
+ StartLibrary(false);
+ Add([
+ 'procedure Run(w: word);',
+ 'begin',
+ 'end;',
+ 'exports',
+ ' Run,',
+ ' run name ''Foo'';',
+ '']);
+ ConvertLibrary;
+ CheckSource('TestLibrary_ExportFunc',
+ LinesToStr([ // statements
+ '']),
+ LinesToStr([
+ '']));
+ CheckResolverUnexpectedHints();
+end;
+
Initialization
RegisterTests([TTestModule]);
end.
diff --git a/avx512-0037785/packages/rtl-extra/fpmake.pp b/avx512-0037785/packages/rtl-extra/fpmake.pp
index 1830dd99db..0421a0eb8a 100644
--- a/avx512-0037785/packages/rtl-extra/fpmake.pp
+++ b/avx512-0037785/packages/rtl-extra/fpmake.pp
@@ -27,8 +27,6 @@ Const
WinsockOSes = [win32,win64,wince,os2,emx,netware,netwlibc];
WinSock2OSes = [win32,win64,wince];
SocketsOSes = UnixLikes+AllAmigaLikeOSes+[netware,netwlibc,os2,emx,wince,win32,win64];
- Socksyscall = [beos,freebsd,haiku,linux,netbsd,openbsd,dragonfly];
- Socklibc = unixlikes-socksyscall;
gpmOSes = [Linux,Android];
AllTargetsextra = ObjectsOSes + UComplexOSes + MatrixOSes+
SerialOSes +PrinterOSes+SocketsOSes+gpmOSes;
@@ -36,6 +34,7 @@ Const
Var
P : TPackage;
T : TTarget;
+ Socksyscall, Socklibc : set of Tos;
begin
With Installer do
@@ -51,6 +50,15 @@ begin
if Defaults.CPU=jvm then
P.OSes := P.OSes - [java,android];
+ Socksyscall := [beos,freebsd,haiku,linux,netbsd,dragonfly];
+ Socklibc := unixlikes-socksyscall;
+{$ifdef FPC_USE_SYSCALL}
+ if Defaults.OS=openbsd then
+ begin
+ system.include(Socksyscall,openbsd);
+ system.exclude(Socklibc,openbsd);
+ end;
+{$endif}
P.Email := '';
P.Description := 'Rtl-extra, RTL not needed for bootstrapping';
P.NeedLibC:= false;
diff --git a/avx512-0037785/packages/rtl-extra/src/bsd/osdefs.inc b/avx512-0037785/packages/rtl-extra/src/bsd/osdefs.inc
index 006f83e4b7..11dac66888 100644
--- a/avx512-0037785/packages/rtl-extra/src/bsd/osdefs.inc
+++ b/avx512-0037785/packages/rtl-extra/src/bsd/osdefs.inc
@@ -27,4 +27,9 @@
{$ifdef darwin}
{$define FPC_USE_LIBC}
{$endif}
+{$ifdef openbsd}
+ {$ifndef FPC_USE_SYSCALL}
+ {$define FPC_USE_LIBC}
+ {$endif}
+{$endif}
diff --git a/avx512-0037785/packages/rtl-objpas/src/inc/dateutil.inc b/avx512-0037785/packages/rtl-objpas/src/inc/dateutil.inc
index 212775196e..1269f3a040 100644
--- a/avx512-0037785/packages/rtl-objpas/src/inc/dateutil.inc
+++ b/avx512-0037785/packages/rtl-objpas/src/inc/dateutil.inc
@@ -1885,7 +1885,7 @@ end;
function TryEncodeTimeInterval(Hour, Min, Sec, MSec: word; out Time: TDateTime): boolean;
begin
- Result:= (Min<60) and (Sec<60) and (MSec<1000);
+ Result:= (Min<60) and (Sec<60) and (MSec<=1000);
If Result then
Time:=TDateTime(cardinal(Hour)*3600000+cardinal(Min)*60000+cardinal(Sec)*1000+MSec)/MSecsPerDay;
end;
diff --git a/avx512-0037785/packages/rtl-objpas/src/inc/variants.pp b/avx512-0037785/packages/rtl-objpas/src/inc/variants.pp
index 4682f3bfae..7e306f6aca 100644
--- a/avx512-0037785/packages/rtl-objpas/src/inc/variants.pp
+++ b/avx512-0037785/packages/rtl-objpas/src/inc/variants.pp
@@ -2351,10 +2351,14 @@ begin
end;
procedure DoVarCast(var aDest : TVarData; const aSource : TVarData; aVarType : LongInt);
+var
+ Handler: TCustomVariantType;
begin
with aSource do
if vType = aVarType then
DoVarCopy(aDest, aSource)
+ else if FindCustomVariantType(vType, Handler) then
+ Handler.CastTo(aDest, aSource, aVarType)
else begin
if (vType = varNull) and NullStrictConvert then
VarCastError(varNull, aVarType);
diff --git a/avx512-0037785/rtl/amiga/powerpc/execf.inc b/avx512-0037785/rtl/amiga/powerpc/execf.inc
index 7aecd3c608..b745f18488 100644
--- a/avx512-0037785/rtl/amiga/powerpc/execf.inc
+++ b/avx512-0037785/rtl/amiga/powerpc/execf.inc
@@ -35,6 +35,10 @@ function SetSignal(newSignals: longword; signalMask: longword): longword; syscal
procedure AddPort(port: PMsgPort); syscall IExec 300;
+function CreateMsgPort(): PMsgPort; syscall IExec 308;
+
+procedure DeleteMsgPort(Port: PMsgPort); syscall IExec 316;
+
function GetMsg(port: PMsgPort): PMessage; syscall IExec 324;
procedure PutMsg(port: PMsgPort; message: PMessage); syscall IExec 328;
procedure RemPort(port: PMsgPort); syscall IExec 332;
@@ -58,6 +62,8 @@ procedure DropInterface(_interface: POS4Interface); syscall IExec 456;
function OpenDevice(devName: PChar; unitNumber: longword;ioRequest: PIORequest; flags: longword): longint; syscall IExec 504;
function CloseDevice(ioRequest: PIORequest): Pointer; syscall IExec 508;
+function CreateIORequest(const IOReplyPort: PMsgPort; Size: LongWord): PIORequest; syscall IExec 512;
+procedure DeleteIORequest(IORequest: PIORequest); syscall IExec 516;
function DoIO(ioRequest: PIORequest): shortint; syscall IExec 528;
diff --git a/avx512-0037785/rtl/i386/cpu.pp b/avx512-0037785/rtl/i386/cpu.pp
index 7ef4af7b53..0ba4844035 100644
--- a/avx512-0037785/rtl/i386/cpu.pp
+++ b/avx512-0037785/rtl/i386/cpu.pp
@@ -70,22 +70,32 @@ unit cpu;
function InterlockedCompareExchange128(var Target: Int128Rec; NewValue: Int128Rec; Comperand: Int128Rec): Int128Rec;
begin
{$if FPC_FULLVERSION >= 30101}
-{$ifndef FPC_PIC}
+{$ifndef FPC_PIC}
if _RTMSupport then
begin
asm
- .Lretry:
+{$ifdef USE_REAL_INSTRUCTIONS}
+ .Lretry:
xbegin .Lretry
+{$else}
+{ 3d: c7 f8 fa ff ff ff xbegin }
+ .byte 0xc7,0xf8, 0xfa, 0xff, 0xff, 0xff
+{$endif}
end;
Result:=Target;
if (Result.Lo=Comperand.Lo) and (Result.Hi=Comperand.Hi) then
Target:=NewValue;
asm
+{$ifdef USE_REAL_INSTRUCTIONS}
xend
+{$else}
+ { 8a: 0f 01 d5 xend }
+ .byte 0x0f, 0x01, 0xd5
+{$endif}
end;
end
else
-{$endif FPC_PIC}
+{$endif FPC_PIC}
{$endif FPC_FULLVERSION >= 30101}
RunError(217);
end;
@@ -119,7 +129,11 @@ unit cpu;
function cr0 : longint;assembler;
asm
+{$ifdef USE_REAL_INSTRUCTIONS}
+ mov eax,cr0
+{$else}
DB 0Fh,20h,0C0h
+{$endif}
{ mov eax,cr0
special registers are not allowed in the assembler
parsers }
@@ -138,8 +152,12 @@ unit cpu;
function XGETBV(i : dword) : int64;assembler;
asm
movl %eax,%ecx
+{$ifdef USE_REAL_INSTRUCTIONS}
+ xgetbv
+{$else}
// older FPCs don't know the xgetbv opcode
.byte 0x0f,0x01,0xd0
+{$endif}
end;
diff --git a/avx512-0037785/rtl/linux/i386/si_prc.inc b/avx512-0037785/rtl/linux/i386/si_prc.inc
index ae0531dd9e..1639445a70 100644
--- a/avx512-0037785/rtl/linux/i386/si_prc.inc
+++ b/avx512-0037785/rtl/linux/i386/si_prc.inc
@@ -45,7 +45,9 @@ var
procedure fpc_geteipasebxlocal; [external name 'fpc_geteipasebx'];
{$endif}
+{$ifndef FPC_USE_LIBC}
procedure InitTLS; [external name 'FPC_INITTLS'];
+{$endif}
procedure _FPC_proc_start; assembler; nostackframe; public name '_start';
asm
@@ -95,9 +97,9 @@ asm
movl %esp,initialstkptr
{$endif FPC_PIC}
-{$if FPC_FULLVERSION>30200}
+{$if (FPC_FULLVERSION>30200) and not defined(FPC_USE_LIBC)}
call InitTLS
-{$endif FPC_FULLVERSION>30200}
+{$endif FPC_FULLVERSION>30200 and not FPC_USE_LIBC}
xorl %ebp,%ebp
call PASCALMAIN
diff --git a/avx512-0037785/rtl/linux/linux.pp b/avx512-0037785/rtl/linux/linux.pp
index 7a31fdf8f1..4c661a81df 100644
--- a/avx512-0037785/rtl/linux/linux.pp
+++ b/avx512-0037785/rtl/linux/linux.pp
@@ -20,7 +20,7 @@ unit Linux;
{$i osdefs.inc}
{$packrecords c}
-{$ifdef FPC_USE_LIBC}
+{$ifdef FPC_USE_LIBC}
{$linklib rt} // for clock* functions
{$endif}
@@ -40,7 +40,7 @@ type
__s32 = Longint;
__u64 = QWord;
__s64 = Int64;
-
+
type
TSysInfo = record
uptime: clong; //* Seconds since boot */
@@ -483,8 +483,8 @@ Type
function clock_getres(clk_id : clockid_t; res : ptimespec) : cint; {$ifdef FPC_USE_LIBC} cdecl; external name 'clock_getres'; {$ENDIF}
function clock_gettime(clk_id : clockid_t; tp: ptimespec) : cint; {$ifdef FPC_USE_LIBC} cdecl; external name 'clock_gettime'; {$ENDIF}
function clock_settime(clk_id : clockid_t; tp : ptimespec) : cint; {$ifdef FPC_USE_LIBC} cdecl; external name 'clock_settime'; {$ENDIF}
-function setregid(rgid,egid : uid_t): cint; {$ifdef FPC_USE_LIBC} cdecl; external name 'setregid'; {$ENDIF}
-function setreuid(ruid,euid : uid_t): cint; {$ifdef FPC_USE_LIBC} cdecl; external name 'setreuid'; {$ENDIF}
+function setregid(rgid,egid : uid_t): cint; {$ifdef FPC_USE_LIBC} cdecl; external name 'setregid'; {$ENDIF}
+function setreuid(ruid,euid : uid_t): cint; {$ifdef FPC_USE_LIBC} cdecl; external name 'setreuid'; {$ENDIF}
Const
STATX_TYPE = $00000001;
@@ -517,7 +517,7 @@ Type
end;
pstatx_timestamp = ^statx_timestamp;
- statx = record
+ tstatx = record
stx_mask : __u32;
stx_blksize : __u32;
stx_attributes : __u64;
@@ -540,9 +540,25 @@ Type
stx_dev_minor : __u32;
__spare2 : array[0..13] of __u64;
end;
- pstatx = ^statx;
+ pstatx = ^tstatx;
+
+ function statx(dfd: cint; filename: pchar; flags,mask: cuint; var buf: tstatx):cint; {$ifdef FPC_USE_LIBC} cdecl; external name 'statx'; {$ENDIF}
+
+Type
+ kernel_time64_t = clonglong;
- function Fpstatx(dfd: cint; filename: pchar; flags,mask: cuint; var buf: statx):cint; {$ifdef FPC_USE_LIBC} cdecl; external name 'statx'; {$ENDIF}
+ kernel_timespec = record
+ tv_sec : kernel_time64_t;
+ tv_nsec : clonglong;
+ end;
+ pkernel_timespec = ^kernel_timespec;
+
+ tkernel_timespecs = array[0..1] of kernel_timespec;
+
+{$ifndef android}
+Function utimensat(dfd: cint; path:pchar;const times:tkernel_timespecs;flags:cint):cint; {$ifdef FPC_USE_LIBC} cdecl; external name 'utimensat'; {$ENDIF}
+Function futimens(fd: cint; const times:tkernel_timespecs):cint; {$ifdef FPC_USE_LIBC} cdecl; external name 'futimens'; {$ENDIF}
+{$endif android}
implementation
@@ -847,18 +863,60 @@ function setregid(rgid,egid : uid_t): cint;
begin
setregid:=do_syscall(syscall_nr_setregid,rgid,egid);
end;
-
+
function setreuid(ruid,euid : uid_t): cint;
begin
setreuid:=do_syscall(syscall_nr_setreuid,ruid,euid);
end;
-function Fpstatx(dfd: cint; filename: pchar; flags,mask: cuint; var buf: statx):cint;
+function statx(dfd: cint; filename: pchar; flags,mask: cuint; var buf: tstatx):cint;
begin
- Fpstatx:=do_syscall(syscall_nr_statx,TSysParam(dfd),TSysParam(filename),TSysParam(flags),TSysParam(mask),TSysParam(@buf));
+ statx:=do_syscall(syscall_nr_statx,TSysParam(dfd),TSysParam(filename),TSysParam(flags),TSysParam(mask),TSysParam(@buf));
end;
-{$endif}
+
+{$ifndef android}
+Function utimensat(dfd: cint; path:pchar;const times:tkernel_timespecs;flags:cint):cint;
+var
+ tsa: Array[0..1] of timespec;
+begin
+{$if sizeof(clong)<=4}
+ utimensat:=do_syscall(syscall_nr_utimensat_time64,dfd,TSysParam(path),TSysParam(@times),0);
+ if (utimensat>=0) or (fpgeterrno<>ESysENOSYS) then
+ exit;
+ { try 32 bit fall back }
+ tsa[0].tv_sec := times[0].tv_sec;
+ tsa[0].tv_nsec := times[0].tv_nsec;
+ tsa[1].tv_sec := times[1].tv_sec;
+ tsa[1].tv_nsec := times[1].tv_nsec;
+ utimensat:=do_syscall(syscall_nr_utimensat,dfd,TSysParam(path),TSysParam(@tsa),0);
+{$else sizeof(clong)<=4}
+ utimensat:=do_syscall(syscall_nr_utimensat,dfd,TSysParam(path),TSysParam(@times),0);
+{$endif sizeof(clong)<=4}
+end;
+
+
+Function futimens(fd: cint; const times:tkernel_timespecs):cint;
+var
+ tsa: Array[0..1] of timespec;
+begin
+{$if sizeof(clong)<=4}
+ futimens:=do_syscall(syscall_nr_utimensat_time64,fd,TSysParam(nil),TSysParam(@times),0);
+ if (futimens>=0) or (fpgeterrno<>ESysENOSYS) then
+ exit;
+ { try 32 bit fall back }
+ tsa[0].tv_sec := times[0].tv_sec;
+ tsa[0].tv_nsec := times[0].tv_nsec;
+ tsa[1].tv_sec := times[1].tv_sec;
+ tsa[1].tv_nsec := times[1].tv_nsec;
+ futimens:=do_syscall(syscall_nr_utimensat,fd,TSysParam(nil),TSysParam(@tsa),0);
+{$else sizeof(clong)<=4}
+ futimens:=do_syscall(syscall_nr_utimensat,fd,TSysParam(nil),TSysParam(@times),0);
+{$endif sizeof(clong)<=4}
+end;
+{$endif android}
+{$endif not FPC_USE_LIBC}
end.
+
diff --git a/avx512-0037785/rtl/linux/m68k/cprt0.as b/avx512-0037785/rtl/linux/m68k/cprt0.as
index 46f8ddc403..0c47f6b308 100644
--- a/avx512-0037785/rtl/linux/m68k/cprt0.as
+++ b/avx512-0037785/rtl/linux/m68k/cprt0.as
@@ -38,6 +38,7 @@ __entry:
lea.l 8(%sp,%d0.l*4),%a0
move.l %a0,operatingsystem_parameter_envp
move.l %sp,%a0 /* argv */
+ move.l %sp,__stkptr
pea (%sp) /* highest available stack address */
pea (%a1) /* termination function provided by kernel */
diff --git a/avx512-0037785/rtl/linux/m68k/dllprt0.as b/avx512-0037785/rtl/linux/m68k/dllprt0.as
index c4f94ee050..e82b3b3f2b 100644
--- a/avx512-0037785/rtl/linux/m68k/dllprt0.as
+++ b/avx512-0037785/rtl/linux/m68k/dllprt0.as
@@ -24,6 +24,7 @@ _startlib:
# This is a normal C function with args (argc,argv,envp)
FPC_SHARED_LIB_START:
link.w %a6,#0
+ move.l %sp,__stkptr
move.l 8(%fp),%d0
move.l %d0,operatingsystem_parameter_argc
move.l 12(%fp),%d0
diff --git a/avx512-0037785/rtl/linux/mips/cprt0.as b/avx512-0037785/rtl/linux/mips/cprt0.as
index 327adf1dcf..7cf2816df9 100644
--- a/avx512-0037785/rtl/linux/mips/cprt0.as
+++ b/avx512-0037785/rtl/linux/mips/cprt0.as
@@ -128,6 +128,11 @@ _start:
.globl main_stub
.type main_stub,@function
main_stub:
+ /* load fp */
+ move $s8,$sp
+ /* set __stkptr value to $s8 */
+ lui $v0,%hi(__stkptr)
+ sw $s8,%lo(__stkptr)($v0)
lui $v0,%hi(__fpc_ret_sp)
sw $sp,%lo(__fpc_ret_sp)($v0)
lui $v0,%hi(__fpc_ret_ra)
diff --git a/avx512-0037785/rtl/linux/mips/prt0.as b/avx512-0037785/rtl/linux/mips/prt0.as
index 17d57ef326..0b624a86a6 100644
--- a/avx512-0037785/rtl/linux/mips/prt0.as
+++ b/avx512-0037785/rtl/linux/mips/prt0.as
@@ -52,6 +52,7 @@ _dynamic_start:
_start:
/* load fp */
move $s8,$sp
+ /* set __stkptr value to $s8 */
lui $at,%hi(__stkptr)
sw $s8,%lo(__stkptr)($at)
diff --git a/avx512-0037785/rtl/linux/si_impl.inc b/avx512-0037785/rtl/linux/si_impl.inc
index a727310551..2b19deaf10 100644
--- a/avx512-0037785/rtl/linux/si_impl.inc
+++ b/avx512-0037785/rtl/linux/si_impl.inc
@@ -16,7 +16,9 @@ procedure PascalMain; external name 'PASCALMAIN';
{$ifdef FPC_HAS_INDIRECT_ENTRY_INFORMATION}
procedure SysEntry(constref info: TEntryInformation); external name 'FPC_SysEntry';
+{$ifndef FPC_USE_LIBC}
procedure SysEntry_InitTLS(constref info: TEntryInformation); external name 'FPC_SysEntry_InitTLS';
+{$endif FPC_USE_LIBC}
var
InitFinalTable : record end; external name 'INITFINAL';
diff --git a/avx512-0037785/rtl/linux/system.pp b/avx512-0037785/rtl/linux/system.pp
index caa4e116c7..4303c61147 100644
--- a/avx512-0037785/rtl/linux/system.pp
+++ b/avx512-0037785/rtl/linux/system.pp
@@ -125,6 +125,9 @@ procedure OsSetupEntryInformation(constref info: TEntryInformation); forward;
TLS handling
*****************************************************************************}
+{ TLS initialization is not required if linking against libc }
+{$if not defined(FPC_USE_LIBC)}
+
{$if defined(CPUARM)}
{$define INITTLS}
Function fpset_tls(p : pointer;size : SizeUInt):cint;
@@ -185,6 +188,8 @@ begin
end;
{$endif defined(CPUX86_64)}
+{$endif not FPC_USE_LIBC}
+
{$ifdef INITTLS}
{ This code initialized the TLS segment for single threaded and static programs.
@@ -323,6 +328,8 @@ begin
info.PascalMain();
end;
+
+{$ifndef FPC_USE_LIBC}
procedure SysEntry_InitTLS(constref info: TEntryInformation);[public,alias:'FPC_SysEntry_InitTLS'];
begin
SetupEntryInformation(info);
@@ -334,6 +341,7 @@ begin
{$endif cpui386}
info.PascalMain();
end;
+{$endif FPC_USE_LIBC}
{$else}
var
@@ -361,6 +369,7 @@ begin
end;
+{$ifdef FPC_USE_LIBC}
procedure SysEntry_InitTLS(constref info: TEntryInformation);[public,alias:'FPC_SysEntry_InitTLS'];
begin
initialstkptr := info.OS.stkptr;
@@ -375,6 +384,7 @@ begin
{$endif cpui386}
info.PascalMain();
end;
+{$endif FPC_USE_LIBC}
{$endif FPC_BOOTSTRAP_INDIRECT_ENTRY}
diff --git a/avx512-0037785/rtl/linux/x86_64/si_prc.inc b/avx512-0037785/rtl/linux/x86_64/si_prc.inc
index 1864e9d559..71804c1343 100644
--- a/avx512-0037785/rtl/linux/x86_64/si_prc.inc
+++ b/avx512-0037785/rtl/linux/x86_64/si_prc.inc
@@ -35,7 +35,9 @@
{$L abitag.o}
+{$ifndef FPC_USE_LIBC}
procedure InitTLS; [external name 'FPC_INITTLS'];
+{$endif}
{******************************************************************************
Process start/halt
@@ -73,7 +75,11 @@ procedure _FPC_proc_start; assembler; nostackframe; public name '_start';
movq %r10,%rdi
xorq %rbp, %rbp
+{$ifdef FPC_USE_LIBC}
+ call SysEntry
+{$else}
call SysEntry_InitTLS
+{$endif}
{$else FPC_HAS_INDIRECT_ENTRY_INFORMATION}
popq %rsi { Pop the argument count. }
movq operatingsystem_parameter_argc@GOTPCREL(%rip),%rax
@@ -90,9 +96,9 @@ procedure _FPC_proc_start; assembler; nostackframe; public name '_start';
movq initialstkptr@GOTPCREL(%rip),%rax
movq %rsp,(%rax)
-{$if FPC_FULLVERSION>30200}
+{$if (FPC_FULLVERSION>30200) and not defined(FPC_USE_LIBC)}
call InitTLS
-{$endif FPC_FULLVERSION>30200}
+{$endif FPC_FULLVERSION>30200 and not FPC_USE_LIBC}
xorq %rbp, %rbp
call PASCALMAIN
diff --git a/avx512-0037785/rtl/linux/x86_64/syscall.inc b/avx512-0037785/rtl/linux/x86_64/syscall.inc
index aad7783a92..1812073032 100644
--- a/avx512-0037785/rtl/linux/x86_64/syscall.inc
+++ b/avx512-0037785/rtl/linux/x86_64/syscall.inc
@@ -20,9 +20,10 @@
procedure mcount; external name 'mcount';
{$endif FPC_PROFILE}
-function FpSysCall(sysnr:TSysParam):TSysResult; assembler;[public,alias:'FPC_SYSCALL0'];
+function FpSysCall(sysnr:TSysParam):TSysResult; assembler; nostackframe; [public,alias:'FPC_SYSCALL0'];
asm
+ pushq %rax { keep stack aligned }
{$ifdef FPC_PROFILE}
pushq sysnr
call mcount
@@ -37,11 +38,13 @@ asm
call seterrno@PLT
movq $-1,%rax
.LSyscOK:
+ popq %rcx { remove alignment }
end;
-function FpSysCall(sysnr,param1 : TSysParam):TSysResult; assembler;[public,alias:'FPC_SYSCALL1'];
+function FpSysCall(sysnr,param1 : TSysParam):TSysResult; assembler; nostackframe; [public,alias:'FPC_SYSCALL1'];
asm
+ pushq %rax { keep stack aligned }
{$ifdef FPC_PROFILE}
pushq sysnr
pushq param1
@@ -59,11 +62,13 @@ asm
call seterrno@PLT
movq $-1,%rax
.LSyscOK:
+ popq %rcx { remove alignment }
end;
-function FpSysCall(sysnr,param1,param2 : TSysParam):TSysResult; assembler;[public,alias:'FPC_SYSCALL2'];
+function FpSysCall(sysnr,param1,param2 : TSysParam):TSysResult; assembler; nostackframe; [public,alias:'FPC_SYSCALL2'];
asm
+ pushq %rax { keep stack aligned }
{$ifdef FPC_PROFILE}
pushq sysnr
pushq param1
@@ -84,11 +89,13 @@ asm
call seterrno@PLT
movq $-1,%rax
.LSyscOK:
+ popq %rcx { remove alignment }
end;
-function FpSysCall(sysnr,param1,param2,param3:TSysParam):TSysResult; assembler;[public,alias:'FPC_SYSCALL3'];
+function FpSysCall(sysnr,param1,param2,param3:TSysParam):TSysResult; assembler; nostackframe; [public,alias:'FPC_SYSCALL3'];
asm
+ pushq %rax { keep stack aligned }
{$ifdef FPC_PROFILE}
pushq sysnr
pushq param1
@@ -112,11 +119,13 @@ asm
call seterrno@PLT
movq $-1,%rax
.LSyscOK:
+ popq %rcx { remove alignment }
end;
-function FpSysCall(sysnr,param1,param2,param3,param4:TSysParam):TSysResult; assembler;[public,alias:'FPC_SYSCALL4'];
+function FpSysCall(sysnr,param1,param2,param3,param4:TSysParam):TSysResult; assembler; nostackframe; [public,alias:'FPC_SYSCALL4'];
asm
+ pushq %rax { keep stack aligned }
{$ifdef FPC_PROFILE}
pushq sysnr
pushq param1
@@ -143,11 +152,13 @@ asm
call seterrno@PLT
movq $-1,%rax
.LSyscOK:
+ popq %rcx { remove alignment }
end;
-function FpSysCall(sysnr,param1,param2,param3,param4,param5 : TSysParam):TSysResult; assembler;[public,alias:'FPC_SYSCALL5'];
+function FpSysCall(sysnr,param1,param2,param3,param4,param5 : TSysParam):TSysResult; assembler; nostackframe; [public,alias:'FPC_SYSCALL5'];
asm
+ pushq %rax { keep stack aligned }
{$ifdef FPC_PROFILE}
pushq sysnr
pushq param1
@@ -177,6 +188,7 @@ asm
call seterrno@PLT
movq $-1,%rax
.LSyscOK:
+ popq %rcx { remove alignment }
end;
diff --git a/avx512-0037785/rtl/objpas/sysconst.pp b/avx512-0037785/rtl/objpas/sysconst.pp
index 39b844dfa2..cefd14f79c 100644
--- a/avx512-0037785/rtl/objpas/sysconst.pp
+++ b/avx512-0037785/rtl/objpas/sysconst.pp
@@ -90,13 +90,13 @@ const
SNoDynLibsSupport = 'Dynamic libraries not supported. Recompile program with dynamic library driver.';
SMissingWStringManager = 'Widestring manager not available. Recompile program with appropriate manager.';
SSigQuit = 'SIGQUIT signal received.';
- SObjectCheckError = 'Object reference is Nil';
+ SObjectCheckError = 'Object reference is Nil or VMT is damaged';
SOSError = 'System error, (OS Code %d):'+LineEnding+'%s';
SOutOfMemory = 'Out of memory';
SOverflow = 'Floating point overflow';
SPrivilege = 'Privileged instruction';
SRangeError = 'Range check error';
- SStackOverflow = 'Stack overflow';
+ SStackOverflow = 'Stack overflow or stack misalignment';
SSafecallException = 'Exception in safecall method';
SiconvError = 'iconv error';
SThreadError = 'Thread error';
diff --git a/avx512-0037785/rtl/objpas/sysutils/syshelpo.inc b/avx512-0037785/rtl/objpas/sysutils/syshelpo.inc
index 0ab24ea753..497d0ef508 100644
--- a/avx512-0037785/rtl/objpas/sysutils/syshelpo.inc
+++ b/avx512-0037785/rtl/objpas/sysutils/syshelpo.inc
@@ -1,8 +1,12 @@
Class Function TORDINALHELPER.Parse(const AString: string): TORDINALTYPE; inline; static;
+var
+ Error: Integer;
begin
- Result:=StrToInt(AString);
+ Val(AString,Result,Error);
+ if Error<>0 then
+ raise EConvertError.CreateFmt(SInvalidInteger,[AString]);
end;
Class Function TORDINALHELPER.Size: Integer; inline; static;
@@ -14,7 +18,7 @@ end;
Class Function TORDINALHELPER.ToString(const AValue: TORDINALTYPE): string; overload; inline; static;
begin
- Result:=IntToStr(AValue);
+ Str(AValue,Result);
end;
Class Function TORDINALHELPER.TryParse(const AString: string; out AValue: TORDINALTYPE): Boolean; inline; static;
@@ -73,7 +77,7 @@ end;
Function TORDINALHELPER.ToString: string; overload; inline;
begin
- Result:=IntToStr(Self);
+ Str(Self,Result);
end;
Function TORDINALHELPER.SetBit(const index: TORDINALBITINDEX) : TORDINALTYPE; inline;
diff --git a/avx512-0037785/rtl/unix/oscdeclh.inc b/avx512-0037785/rtl/unix/oscdeclh.inc
index 291e5e2f70..abfabe073a 100644
--- a/avx512-0037785/rtl/unix/oscdeclh.inc
+++ b/avx512-0037785/rtl/unix/oscdeclh.inc
@@ -180,4 +180,6 @@ const
{$endif}
function FpTime (tloc:ptime_t): time_t; cdecl; external clib name 'time';
-
+{$if defined(linux)}
+ function FpSchedGetAffinity(pid : pid_t;cpusetsize : size_t;mask : pcpu_set_t) : cint; cdecl; external clib name 'sched_getaffinity';
+{$endif}
diff --git a/avx512-0037785/rtl/unix/sysutils.pp b/avx512-0037785/rtl/unix/sysutils.pp
index 68520a7e99..c35d28be79 100644
--- a/avx512-0037785/rtl/unix/sysutils.pp
+++ b/avx512-0037785/rtl/unix/sysutils.pp
@@ -55,6 +55,15 @@ uses
{$DEFINE HAVECLOCKGETTIME}
{$ENDIF}
+{$if defined(LINUX)}
+ {$if sizeof(clong)<8}
+ {$DEFINE USE_STATX}
+ {$DEFINE USE_UTIMENSAT}
+ {$endif sizeof(clong)<=4}
+
+ {$DEFINE USE_FUTIMES}
+{$endif}
+
{ Include platform independent interface part }
{$i sysutilh.inc}
@@ -547,12 +556,26 @@ begin
end;
end;
+
Function FileAge (Const FileName : RawByteString): Int64;
Var
Info : Stat;
SystemFileName: RawByteString;
+{$ifdef USE_STATX}
+ Infox : TStatx;
+{$endif USE_STATX}
begin
SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
+
+{$ifdef USE_STATX}
+ { first try statx }
+ if (statx(AT_FDCWD,pchar(SystemFileName),0,STATX_MTIME or STATX_MODE,Infox)>=0) and not(fpS_ISDIR(Infox.stx_mode)) then
+ begin
+ Result:=Infox.stx_mtime.tv_sec;
+ exit;
+ end;
+{$endif USE_STATX}
+
If (fpstat(pchar(SystemFileName),Info)<0) or fpS_ISDIR(info.st_mode) then
exit(-1)
else
@@ -587,6 +610,36 @@ begin
end;
+{$ifdef USE_STATX}
+Function LinuxToWinAttr (const FN : RawByteString; Const Info : TStatx) : Longint;
+Var
+ LinkInfo : Stat;
+ nm : RawByteString;
+begin
+ Result:=faArchive;
+ If fpS_ISDIR(Info.stx_mode) then
+ Result:=Result or faDirectory;
+ nm:=ExtractFileName(FN);
+ If (Length(nm)>=2) and
+ (nm[1]='.') and
+ (nm[2]<>'.') then
+ Result:=Result or faHidden;
+ If (Info.stx_Mode and S_IWUSR)=0 Then
+ Result:=Result or faReadOnly;
+ If fpS_ISSOCK(Info.stx_mode) or fpS_ISBLK(Info.stx_mode) or fpS_ISCHR(Info.stx_mode) or fpS_ISFIFO(Info.stx_mode) Then
+ Result:=Result or faSysFile;
+ If fpS_ISLNK(Info.stx_mode) Then
+ begin
+ Result:=Result or faSymLink;
+ // Windows reports if the link points to a directory.
+ { as we are only interested in the st_mode field here, we do not need to use statx }
+ if (fpstat(pchar(FN),LinkInfo)>=0) and fpS_ISDIR(LinkInfo.st_mode) then
+ Result := Result or faDirectory;
+ end;
+end;
+{$endif USE_STATX}
+
+
function FileGetSymLinkTarget(const FileName: RawByteString; out SymLinkRec: TRawbyteSymLinkRec): Boolean;
var
Info : Stat;
@@ -874,26 +927,54 @@ end;
Function FindGetFileInfo(const s: RawByteString; var f: TAbstractSearchRec; var Name: RawByteString):boolean;
Var
+{$ifdef USE_STATX}
+ stx : linux.tstatx;
+{$endif USE_STATX}
st : baseunix.stat;
WinAttr : longint;
begin
+{$ifdef USE_STATX}
if Assigned(f.FindHandle) and ( (PUnixFindData(F.FindHandle)^.searchattr and faSymlink) > 0) then
- FindGetFileInfo:=(fplstat(pointer(s),st)=0)
+ FindGetFileInfo:=statx(AT_FDCWD,pointer(s),AT_SYMLINK_NOFOLLOW,STATX_ALL,stx)=0
else
- FindGetFileInfo:=(fpstat(pointer(s),st)=0);
- if not FindGetFileInfo then
- exit;
- WinAttr:=LinuxToWinAttr(s,st);
- FindGetFileInfo:=(WinAttr and Not(PUnixFindData(f.FindHandle)^.searchattr))=0;
-
+ FindGetFileInfo:=statx(AT_FDCWD,pointer(s),0,STATX_ALL,stx)=0;
if FindGetFileInfo then
begin
- Name:=ExtractFileName(s);
- f.Attr:=WinAttr;
- f.Size:=st.st_Size;
- f.Mode:=st.st_mode;
- f.Time:=st.st_mtime;
- FindGetFileInfo:=true;
+ WinAttr:=LinuxToWinAttr(s,stx);
+ FindGetFileInfo:=(WinAttr and Not(PUnixFindData(f.FindHandle)^.searchattr))=0;
+
+ if FindGetFileInfo then
+ begin
+ Name:=ExtractFileName(s);
+ f.Attr:=WinAttr;
+ f.Size:=stx.stx_Size;
+ f.Mode:=stx.stx_mode;
+ f.Time:=stx.stx_mtime.tv_sec;
+ FindGetFileInfo:=true;
+ end;
+ end
+ { no statx? try stat }
+ else if fpgeterrno=ESysENOSYS then
+{$endif USE_STATX}
+ begin
+ if Assigned(f.FindHandle) and ( (PUnixFindData(F.FindHandle)^.searchattr and faSymlink) > 0) then
+ FindGetFileInfo:=(fplstat(pointer(s),st)=0)
+ else
+ FindGetFileInfo:=(fpstat(pointer(s),st)=0);
+ if not FindGetFileInfo then
+ exit;
+ WinAttr:=LinuxToWinAttr(s,st);
+ FindGetFileInfo:=(WinAttr and Not(PUnixFindData(f.FindHandle)^.searchattr))=0;
+
+ if FindGetFileInfo then
+ begin
+ Name:=ExtractFileName(s);
+ f.Attr:=WinAttr;
+ f.Size:=st.st_Size;
+ f.Mode:=st.st_mode;
+ f.Time:=st.st_mtime;
+ FindGetFileInfo:=true;
+ end;
end;
end;
@@ -996,22 +1077,44 @@ End;
Function FileGetDate (Handle : Longint) : Int64;
-
-Var Info : Stat;
-
+Var
+ Info : Stat;
+{$ifdef USE_STATX}
+ Infox : TStatx;
+{$endif USE_STATX}
+ Char0 : char;
begin
- If (fpFStat(Handle,Info))<0 then
- Result:=-1
- else
- Result:=Info.st_Mtime;
+ Result:=-1;
+{$ifdef USE_STATX}
+ Char0:=#0;
+ if statx(Handle,@Char0,AT_EMPTY_PATH,STATX_MTIME,Infox)=0 then
+ Result:=Infox.stx_Mtime.tv_sec
+ else if fpgeterrno=ESysENOSYS then
+{$endif USE_STATX}
+ begin
+ If fpFStat(Handle,Info)=0 then
+ Result:=Info.st_Mtime;
+ end;
end;
Function FileSetDate (Handle : Longint;Age : Int64) : Longint;
-
+{$ifdef USE_FUTIMES}
+var
+ times : tkernel_timespecs;
+{$endif USE_FUTIMES}
begin
- // Impossible under Linux from FileHandle !!
+ Result:=0;
+{$ifdef USE_FUTIMES}
+ times[0].tv_sec:=Age;
+ times[0].tv_nsec:=0;
+ times[1].tv_sec:=Age;
+ times[1].tv_nsec:=0;
+ if futimens(Handle,times) = -1 then
+ Result:=fpgeterrno;
+{$else USE_FUTIMES}
FileSetDate:=-1;
+{$endif USE_FUTIMES}
end;
@@ -1068,14 +1171,29 @@ end;
Function FileSetDate (Const FileName : RawByteString; Age : Int64) : Longint;
var
SystemFileName: RawByteString;
+{$ifdef USE_UTIMENSAT}
+ times : tkernel_timespecs;
+{$endif USE_UTIMENSAT}
t: TUTimBuf;
begin
SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
Result:=0;
- t.actime:= Age;
- t.modtime:=Age;
- if fputime(PChar(SystemFileName), @t) = -1 then
+{$ifdef USE_UTIMENSAT}
+ times[0].tv_sec:=Age;
+ times[0].tv_nsec:=0;
+ times[1].tv_sec:=Age;
+ times[1].tv_nsec:=0;
+ if utimensat(AT_FDCWD,PChar(SystemFileName),times,0) = -1 then
Result:=fpgeterrno;
+ if fpgeterrno=ESysENOSYS then
+{$endif USE_UTIMENSAT}
+ begin
+ Result:=0;
+ t.actime:= Age;
+ t.modtime:=Age;
+ if fputime(PChar(SystemFileName), @t) = -1 then
+ Result:=fpgeterrno;
+ end
end;
{****************************************************************************
diff --git a/avx512-0037785/tests/Makefile b/avx512-0037785/tests/Makefile
index b9676a929a..e908b07b74 100644
--- a/avx512-0037785/tests/Makefile
+++ b/avx512-0037785/tests/Makefile
@@ -2423,9 +2423,9 @@ LOGEXT=.testlog .tbslog .tbflog .webtbslog .webtbflog
TESTUNITDIRS=system dos crt objects strings sysutils math sharemem strutils matrix lineinfo ucomplex fpwidestring cpu fmtbcd windows classes character dateutil fpcunit softfpu variants sortbase sortalgs linux unixutil types nullable
TESTDIRECTDIRS=
TESTSUBDIRS=cg cg/variants cg/cdecl cpu16 cpu16/i8086 library opt $(addprefix units/,$(TESTUNITDIRS))
-TESTPACKAGESDIRS=win-base webtbs hash fcl-registry fcl-process zlib fcl-db fcl-xml cocoaint bzip2
+TESTPACKAGESDIRS=win-base webtbs hash fcl-registry fcl-process zlib fcl-db fcl-xml cocoaint bzip2 fcl-net
TESTPACKAGESUBDIRS=$(addprefix packages/,$(TESTPACKAGESDIRS))
-TESTPACKAGESDIRECTDIRS=rtl-objpas rtl-generics hash regexpr
+TESTPACKAGESDIRECTDIRS=rtl-objpas rtl-generics hash regexpr fcl-registry
TESTPACKAGESDIRECTSUBDIRS=$(addprefix ../packages/,$(addsuffix /tests,$(TESTPACKAGESDIRECTDIRS)))
ifdef QUICKTEST
export QUICKTEST
diff --git a/avx512-0037785/tests/Makefile.fpc b/avx512-0037785/tests/Makefile.fpc
index 5e6dd2bd2f..15e765d5c4 100644
--- a/avx512-0037785/tests/Makefile.fpc
+++ b/avx512-0037785/tests/Makefile.fpc
@@ -162,9 +162,9 @@ LOGEXT=.testlog .tbslog .tbflog .webtbslog .webtbflog
TESTUNITDIRS=system dos crt objects strings sysutils math sharemem strutils matrix lineinfo ucomplex fpwidestring cpu fmtbcd windows classes character dateutil fpcunit softfpu variants sortbase sortalgs linux unixutil types nullable
TESTDIRECTDIRS=
TESTSUBDIRS=cg cg/variants cg/cdecl cpu16 cpu16/i8086 library opt $(addprefix units/,$(TESTUNITDIRS))
-TESTPACKAGESDIRS=win-base webtbs hash fcl-registry fcl-process zlib fcl-db fcl-xml cocoaint bzip2
+TESTPACKAGESDIRS=win-base webtbs hash fcl-registry fcl-process zlib fcl-db fcl-xml cocoaint bzip2 fcl-net
TESTPACKAGESUBDIRS=$(addprefix packages/,$(TESTPACKAGESDIRS))
-TESTPACKAGESDIRECTDIRS=rtl-objpas rtl-generics hash regexpr
+TESTPACKAGESDIRECTDIRS=rtl-objpas rtl-generics hash regexpr fcl-registry
TESTPACKAGESDIRECTSUBDIRS=$(addprefix ../packages/,$(addsuffix /tests,$(TESTPACKAGESDIRECTDIRS)))
ifdef QUICKTEST
diff --git a/avx512-0037785/tests/test/cg/tpara4.pp b/avx512-0037785/tests/test/cg/tpara4.pp
new file mode 100644
index 0000000000..f175a553eb
--- /dev/null
+++ b/avx512-0037785/tests/test/cg/tpara4.pp
@@ -0,0 +1,22 @@
+{ This test ensures that a "const TVarData" parameter is passed as a reference.
+ This is required for Delphi compatibility as implementers of IVarInvokable or
+ inheritors of TInvokableVariantType need to modify the variant data by using
+ a pointer to the TVarData because it's passed as const and thus not modifyable
+ by itself.
+ This behavior is documented in so far as the C++ builder documentation shows
+ that the same parameter is implemented as "const&". }
+
+program tpara4;
+
+var
+ d: TVarData;
+
+procedure Test(const v: TVarData);
+begin
+ if @d <> @v then
+ Halt(1);
+end;
+
+begin
+ Test(d);
+end.
diff --git a/avx512-0037785/tests/test/theapthread.pp b/avx512-0037785/tests/test/theapthread.pp
index 44f51bf000..36689148ab 100644
--- a/avx512-0037785/tests/test/theapthread.pp
+++ b/avx512-0037785/tests/test/theapthread.pp
@@ -15,12 +15,14 @@ type
tpair = class;
tproducethread = class(tthread)
+ running: boolean;
pair: tpair;
constructor create(apair: tpair);
procedure execute; override;
end;
tconsumethread = class(tthread)
+ running: boolean;
pair: tpair;
constructor create(apair: tpair);
procedure execute; override;
@@ -197,11 +199,13 @@ end;
procedure tproducethread.execute;
begin
+ running:=true;
producer(pair);
end;
procedure tconsumethread.execute;
begin
+ running:=true;
consumer(pair);
end;
@@ -221,7 +225,12 @@ begin
pairs[i] := tpair.create;
for i := low(pairs) to high(pairs) do
pairs[i].resume;
- sleep(1500);
+
+ { wait till all threads are really resumed }
+ for i := low(pairs) to high(pairs) do
+ while not(pairs[i].produce_thread.running) or not(pairs[i].consume_thread.running) do
+ sleep(100);
+
done := true;
for i := low(pairs) to high(pairs) do
begin
diff --git a/avx512-0037785/tests/test/units/linux/tfutimesen.pp b/avx512-0037785/tests/test/units/linux/tfutimesen.pp
new file mode 100644
index 0000000000..797f51fba3
--- /dev/null
+++ b/avx512-0037785/tests/test/units/linux/tfutimesen.pp
@@ -0,0 +1,84 @@
+{ %target=linux }
+uses
+ ctypes,baseunix,linux;
+
+var
+ un : utsname;
+ res : cint;
+ f1,f2 : text;
+ err : word;
+ mystatx1,mystatx2 : tstatx;
+ times : tkernel_timespecs;
+ st,major,minor : string;
+ i,p,e : longint;
+ major_release, minor_release : longint;
+begin
+ fpuname(un);
+ st:=un.release;
+ for i:=1 to UTSNAME_LENGTH do
+ if st[i]='.' then
+ begin
+ p:=i;
+ major:=system.copy(st,1,p-1);
+ system.val(major,major_release,err);
+ if err<>0 then
+ begin
+ writeln('Unable to parse first part of linux version ',st,'(',major,') correctly');
+ halt(2);
+ end;
+ break;
+ end;
+
+ for i:=p+1 to UTSNAME_LENGTH do
+ if st[i]='.' then
+ begin
+ e:=i;
+ minor:=system.copy(st,p+1,e-p-1);
+ system.val(minor,minor_release,err);
+ if err<>0 then
+ begin
+ writeln('Unable to second part of parse linux version ',st,'i(',minor,') correctly');
+ halt(2);
+ end;
+ break;
+ end;
+ if (major_release<4) or ((major_release=4) and (minor_release<11)) then
+ begin
+ writeln('This version of Linux: ',st,' does not have fstatx syscall');
+ halt(0);
+ end
+ else
+ writeln('This linux version ',st,' should support statx syscall');
+
+ assign(f1,'tutimensat1.txt');
+ rewrite(f1);
+ write(f1,'ccccc');
+ assign(f2,'tutimensat2.txt');
+ rewrite(f2);
+ write(f2,'ccccc');
+
+ res:=statx(AT_FDCWD,'tutimensat1.txt',AT_SYMLINK_NOFOLLOW,STATX_ALL,mystatx1);
+ if res<>0 then
+ halt(1);
+ times[0].tv_sec:=mystatx1.stx_atime.tv_sec;
+ times[0].tv_nsec:=mystatx1.stx_atime.tv_nsec;
+ times[1].tv_sec:=mystatx1.stx_mtime.tv_sec;
+ times[1].tv_nsec:=mystatx1.stx_mtime.tv_nsec;
+ res:=futimens(textrec(f2).handle,times);
+ if res<>0 then
+ halt(1);
+ res:=statx(AT_FDCWD,'tutimensat2.txt',AT_SYMLINK_NOFOLLOW,STATX_ALL,mystatx2);
+ if res<>0 then
+ halt(1);
+
+ close(f1);
+ close(f2);
+
+ erase(f1);
+ erase(f2);
+
+ if (mystatx1.stx_atime.tv_sec<>mystatx2.stx_atime.tv_sec) or (mystatx1.stx_atime.tv_nsec<>mystatx2.stx_atime.tv_nsec) or
+ (mystatx1.stx_mtime.tv_sec<>mystatx2.stx_mtime.tv_sec) or (mystatx1.stx_mtime.tv_nsec<>mystatx2.stx_mtime.tv_nsec) then
+ halt(1);
+ writeln('ok');
+end.
diff --git a/avx512-0037785/tests/test/units/linux/tstatx.pp b/avx512-0037785/tests/test/units/linux/tstatx.pp
index 360b11a356..78798f08c3 100644
--- a/avx512-0037785/tests/test/units/linux/tstatx.pp
+++ b/avx512-0037785/tests/test/units/linux/tstatx.pp
@@ -1,10 +1,10 @@
{ %target=linux }
uses
ctypes,baseunix,linux;
-
+
var
un : utsname;
- mystatx : statx;
+ mystatx : tstatx;
res : cint;
f : text;
st,major,minor : string;
@@ -21,13 +21,13 @@ begin
major:=system.copy(st,1,p-1);
system.val(major,major_release,err);
if err<>0 then
- begin
+ begin
writeln('Unable to parse first part of linux version ',st,'(',major,') correctly');
halt(2);
end;
break;
end;
-
+
for i:=p+1 to UTSNAME_LENGTH do
if st[i]='.' then
begin
@@ -35,25 +35,25 @@ begin
minor:=system.copy(st,p+1,e-p-1);
system.val(minor,minor_release,err);
if err<>0 then
- begin
+ begin
writeln('Unable to second part of parse linux version ',st,'i(',minor,') correctly');
halt(2);
end;
break;
end;
- if (major_release<4) or (minor_release<11) then
+ if (major_release<4) or ((major_release=4) and (minor_release<11)) then
begin
writeln('This version of Linux: ',st,' does not have fstatx syscall');
halt(0);
end
else
writeln('This linux version ',st,' should support statx syscall');
-
+
assign(f,'test.txt');
rewrite(f);
write(f,'ccccc');
close(f);
- res:=fpstatx(AT_FDCWD,'test.txt',AT_SYMLINK_NOFOLLOW,STATX_ALL,mystatx);
+ res:=statx(AT_FDCWD,'test.txt',AT_SYMLINK_NOFOLLOW,STATX_ALL,mystatx);
erase(f);
if res<>0 then
begin
diff --git a/avx512-0037785/tests/test/units/linux/tutimensat.pp b/avx512-0037785/tests/test/units/linux/tutimensat.pp
new file mode 100644
index 0000000000..e7fc443bcb
--- /dev/null
+++ b/avx512-0037785/tests/test/units/linux/tutimensat.pp
@@ -0,0 +1,83 @@
+{ %target=linux }
+uses
+ ctypes,baseunix,linux;
+
+var
+ un : utsname;
+ res : cint;
+ f1,f2 : text;
+ err : word;
+ mystatx1,mystatx2 : tstatx;
+ times : tkernel_timespecs;
+ st,major,minor : string;
+ i,p,e : longint;
+ major_release, minor_release : longint;
+begin
+ fpuname(un);
+ st:=un.release;
+ for i:=1 to UTSNAME_LENGTH do
+ if st[i]='.' then
+ begin
+ p:=i;
+ major:=system.copy(st,1,p-1);
+ system.val(major,major_release,err);
+ if err<>0 then
+ begin
+ writeln('Unable to parse first part of linux version ',st,'(',major,') correctly');
+ halt(2);
+ end;
+ break;
+ end;
+
+ for i:=p+1 to UTSNAME_LENGTH do
+ if st[i]='.' then
+ begin
+ e:=i;
+ minor:=system.copy(st,p+1,e-p-1);
+ system.val(minor,minor_release,err);
+ if err<>0 then
+ begin
+ writeln('Unable to second part of parse linux version ',st,'i(',minor,') correctly');
+ halt(2);
+ end;
+ break;
+ end;
+ if (major_release<4) or ((major_release=4) and (minor_release<11)) then
+ begin
+ writeln('This version of Linux: ',st,' does not have fstatx syscall');
+ halt(0);
+ end
+ else
+ writeln('This linux version ',st,' should support statx syscall');
+
+ assign(f1,'tutimensat1.txt');
+ rewrite(f1);
+ write(f1,'ccccc');
+ close(f1);
+ assign(f2,'tutimensat2.txt');
+ rewrite(f2);
+ write(f2,'ccccc');
+ close(f2);
+
+ res:=statx(AT_FDCWD,'tutimensat1.txt',AT_SYMLINK_NOFOLLOW,STATX_ALL,mystatx1);
+ if res<>0 then
+ halt(1);
+ times[0].tv_sec:=mystatx1.stx_atime.tv_sec;
+ times[0].tv_nsec:=mystatx1.stx_atime.tv_nsec;
+ times[1].tv_sec:=mystatx1.stx_mtime.tv_sec;
+ times[1].tv_nsec:=mystatx1.stx_mtime.tv_nsec;
+ res:=utimensat(AT_FDCWD,'tutimensat2.txt',times,0);
+ if res<>0 then
+ halt(1);
+ res:=statx(AT_FDCWD,'tutimensat2.txt',AT_SYMLINK_NOFOLLOW,STATX_ALL,mystatx2);
+ if res<>0 then
+ halt(1);
+
+ erase(f1);
+ erase(f2);
+
+ if (mystatx1.stx_atime.tv_sec<>mystatx2.stx_atime.tv_sec) or (mystatx1.stx_atime.tv_nsec<>mystatx2.stx_atime.tv_nsec) or
+ (mystatx1.stx_mtime.tv_sec<>mystatx2.stx_mtime.tv_sec) or (mystatx1.stx_mtime.tv_nsec<>mystatx2.stx_mtime.tv_nsec) then
+ halt(1);
+ writeln('ok');
+end.
diff --git a/avx512-0037785/tests/test/units/sysutils/tfile1.pp b/avx512-0037785/tests/test/units/sysutils/tfile1.pp
index 578976f2c5..ddca3956e6 100644
--- a/avx512-0037785/tests/test/units/sysutils/tfile1.pp
+++ b/avx512-0037785/tests/test/units/sysutils/tfile1.pp
@@ -32,6 +32,19 @@ BEGIN
if FileSetDate('datetest.dat', DateTimeToFileDate(dateTime))<>0 then
do_error(1002);
+ dateTime := IncMonth(Now, -1);
+ Assign(f,'datetest.dat');
+ Rewrite(f);
+ if FileSetDate(filerec(f).handle, DateTimeToFileDate(dateTime))<>0 then
+ do_error(1003);
+ Close(f);
+
+ Assign(f,'datetest.dat');
+ Reset(f);
+ if FileGetDate(filerec(f).handle)<>DateTimeToFileDate(dateTime) then
+ do_error(1004);
+ Close(f);
+
if FileExists('datetest.dat') then
begin
Assign(f,'datetest.dat');
diff --git a/avx512-0037785/tests/test/units/sysutils/tfileage.pp b/avx512-0037785/tests/test/units/sysutils/tfileage.pp
new file mode 100644
index 0000000000..7710082ea6
--- /dev/null
+++ b/avx512-0037785/tests/test/units/sysutils/tfileage.pp
@@ -0,0 +1,18 @@
+uses
+ sysutils;
+begin
+ if 3600*24*(now()-FileDateToDateTime(FileAge(paramstr(0))))>7200 then
+ begin
+ writeln('FileAge returns: ',FileDateToDateTime(FileAge(paramstr(0))));
+ writeln('Compilation time and run time differ too much, SysUtils.FileAge buggy?');
+ halt(1);
+ end;
+
+ { test with relative path }
+ if 3600*24*(now()-FileDateToDateTime(FileAge(ExtractRelativePath(GetCurrentDir+DirectorySeparator,paramstr(0)))))>7200 then
+ begin
+ writeln('FileAge returns: ',FileDateToDateTime(FileAge(paramstr(0))));
+ writeln('Compilation time and run time differ too much, SysUtils.FileAge buggy?');
+ halt(1);
+ end;
+end.
diff --git a/avx512-0037785/tests/utils/testsuite/utests.pp b/avx512-0037785/tests/utils/testsuite/utests.pp
index e40f57922c..cca795028b 100644
--- a/avx512-0037785/tests/utils/testsuite/utests.pp
+++ b/avx512-0037785/tests/utils/testsuite/utests.pp
@@ -153,13 +153,16 @@ const
faction_compare_with_next = 6;
faction_compare2_with_previous = 7;
faction_compare2_with_next = 8;
+ faction_compare_both_with_previous = 9;
+ faction_compare_both_with_next = 10;
+
Function TestResultsTableName(const RunId : String) : string;
var
RunIDVal : qword;
Error : word;
begin
- system.val (RunId,RunIdVal,error);
+ system.val (Trim(RunId),RunIdVal,error);
if (error<>0) then
result:='ErrorTable'
else if (RunIdVal <= LastOldTestRun) then
@@ -347,6 +350,18 @@ begin
FCompareRunID:=FNext2RunID;
ShowRunComparison;
end;
+ faction_compare_both_with_previous :
+ begin
+ FRunID:=FPreviousRunID;
+ FCompareRunID:=FPrevious2RunID;
+ ShowRunComparison;
+ end;
+ faction_compare_both_with_next :
+ begin
+ FRunID:=FNextRunID;
+ FCompareRunID:=FNext2RunID;
+ ShowRunComparison;
+ end;
{$ifdef TEST}
98 :
begin
@@ -402,6 +417,10 @@ begin
FAction:=faction_compare2_with_previous
else if S='Compare_right_to_next' then
FAction:=faction_compare2_with_next
+ else if S='Compare_both_to_previous' then
+ FAction:=faction_compare_both_with_previous
+ else if S='Compare_both_to_next' then
+ FAction:=faction_compare_both_with_next
else
FAction:=StrToIntDef(S,0);
S:=RequestVariables['limit'];
@@ -1134,7 +1153,7 @@ Const
SGetRunData = 'SELECT TU_ID,TU_DATE,TC_NAME,TO_NAME,' +
'TU_SUBMITTER,TU_MACHINE,TU_COMMENT,TV_VERSION,'+
'TU_CATEGORY_FK,TU_SVNCOMPILERREVISION,TU_SVNRTLREVISION,'+
- 'TU_COMPILERDATE,'+
+ 'TU_COMPILERDATE,TU_COMPILERFULLVERSION,'+
'TU_SVNPACKAGESREVISION,TU_SVNTESTSREVISION,'+
'(TU_SUCCESSFULLYFAILED+TU_SUCCESFULLYCOMPILED+TU_SUCCESSFULLYRUN) AS OK,'+
'(TU_FAILEDTOCOMPILE+TU_FAILEDTORUN+TU_FAILEDTOFAIL) as Failed,'+
@@ -1150,12 +1169,70 @@ Const
Var
- Q1,Q2 : TSQLQuery;
+ Q1, Q2 : TSQLQuery;
F : TField;
- SC : string;
- Date1, Date2: TDateTime;
- AddNewPar : boolean;
- CompilerDate1, CompilerDate2: TDateTime;
+ SC, FRight : string;
+ Date1, Date2 : TDateTime;
+ AddNewPar, same_date : boolean;
+ CompilerDate1, CompilerDate2 : TDateTime;
+
+ procedure EmitOneRow(RowTitle,FieldLeft,FieldRight : String; is_same : boolean);
+ var
+ FieldColor : string;
+ begin
+ if (FieldRight='') then
+ FieldColor:=''
+ else if is_same then
+ FieldColor:='style="color:green;"'
+ else
+ FieldColor:='style="color:red;"';
+ With FHTMLWriter do
+ begin
+ RowNext;
+ if FieldColor<>'' then
+ begin
+ TagStart('TD',FieldColor);
+ end
+ else
+ CellStart;
+ LDumpLn(RowTitle);
+ if FieldColor<>'' then
+ begin
+ CellEnd;
+ TagStart('TD',FieldColor);
+ end
+ else
+ CellNext;
+ LDumpLn(FieldLeft);
+ if FieldColor<>'' then
+ begin
+ CellEnd;
+ TagStart('TD',FieldColor);
+ end
+ else
+ CellNext;
+ LDumpLn(FieldRight);
+ CellEnd;
+ end;
+ end;
+ procedure EmitOneRow(RowTitle,FieldLeft,FieldRight : String);
+ var
+ is_same : boolean;
+ begin
+ is_same:=(FieldLeft=FieldRight);
+ EmitOneRow(RowTitle,FieldLeft,FieldRight,is_same);
+ end;
+ procedure EmitRow(RowTitle,FieldName : String);
+ var
+ FieldLeft, FieldRight : String;
+ begin
+ FieldLeft:=Q1.FieldByName(FieldName).AsString;
+ if Q2=nil then
+ FieldRight:=''
+ else
+ FieldRight:=Q2.FieldByName(FieldName).AsString;
+ EmitOneRow(RowTitle,FieldLeft,FieldRight);
+ end;
begin
Result:=(FRunID<>'');
If Result then
@@ -1191,172 +1268,99 @@ begin
CellNext;
EmitInput('run2id',FCompareRunID);
CellEnd;
- RowNext;
- CellStart;
- DumpLn('Operating system:');
- CellNext;
- DumpLn(Q1.FieldByName('TO_NAME').AsString);
- CellNext;
- if Q2 <> nil then
- DumpLn(Q2.FieldByName('TO_NAME').AsString);
- CellEnd;
- RowNext;
- CellStart;
- DumpLn('Processor:');
- CellNext;
- DumpLn(Q1.FieldByName('TC_NAME').AsString);
- CellNext;
- if Q2 <> nil then
- DumpLn(Q2.FieldByName('TC_NAME').AsString);
- CellEnd;
- RowNext;
- CellStart;
- DumpLn('Version:');
- CellNext;
- DumpLn(Q1.FieldByNAme('TV_VERSION').AsString);
- CellNext;
- if Q2 <> nil then
- DumpLn(Q2.FieldByNAme('TV_VERSION').AsString);
- CellEnd;
- RowNext;
- CellStart;
- DumpLn('Fails/OK/Total:');
- CellNext;
- Dump(Q1.FieldByName('Failed').AsString);
- Dump('/'+Q1.FieldByName('OK').AsString);
- DumpLn('/'+Q1.FieldByName('Total').AsString);
- CellNext;
- if Q2 <> nil then
- begin
- Dump(Q2.FieldByName('Failed').AsString);
- Dump('/'+Q2.FieldByName('Ok').AsString);
- DumpLn('/'+Q2.FieldByName('Total').AsString);
- end;
- CellEnd;
- RowNext;
- CellStart;
- DumpLn('Comment:');
- CellNext;
- DumpLn(Q1.FieldByName('TU_COMMENT').AsString);
- CellNext;
- if Q2 <> nil then
- DumpLn(Q2.FieldByName('TU_COMMENT').AsString);
- CellEnd;
- RowNext;
- CellStart;
- DumpLn('Machine:');
- CellNext;
- DumpLn(Q1.FieldByName('TU_MACHINE').AsString);
- CellNext;
- if Q2 <> nil then
- DumpLn(Q2.FieldByName('TU_MACHINE').AsString);
- CellEnd;
- if GetCategoryName(FCategory)<>'All' then
+ EmitRow('Operating system:','TO_NAME');
+ EmitRow('Processor:','TC_NAME');
+ EmitRow('Version:','TV_VERSION');
+ if Q2 = nil then
+ FRight:=''
+ else
begin
- RowNext;
- CellStart;
- DumpLn('Category:');
- CellNext;
- DumpLn(GetCategoryName(Q1.FieldByName('TU_CATEGORY_FK').AsString));
- CellNext;
- if Q2 <> nil then
- DumpLn(GetCategoryName(Q2.FieldByName('TU_CATEGORY_FK').AsString));
- CellEnd;
+ FRight:=Q2.FieldByName('Failed').AsString+
+ '/'+Q2.FieldByName('Ok').AsString+
+ '/'+Q2.FieldByName('Total').AsString;
end;
+ EmitOneRow('Fails/OK/Total:',
+ Q1.FieldByName('Failed').AsString+
+ '/'+Q1.FieldByName('OK').AsString+
+ '/'+Q1.FieldByName('Total').AsString,
+ FRight);
+ EmitRow('Version:','TV_VERSION');
+ EmitRow('Full version:','TU_COMPILERFULLVERSION');
+ EmitRow('Comment:','TU_COMMENT');
+ EmitRow('Machine:','TU_MACHINE');
+ if GetCategoryName(FCategory)<>'All' then
+ EmitRow('Category:','TU_CATEGORY_FK');
If GetCategoryName(FCategory)<>'DB' then
begin
- RowNext;
- CellStart;
- DumpLn('SVN Revisions:');
- CellNext;
- SC:=Q1.FieldByName('svnrev').AsString;
- if (SC<>'') then
- FormatSVNData(SC);
- LDumpLn(SC);
- CellNext;
- if Q2 <> nil then
- begin
- SC:=Q2.FieldByName('svnrev').AsString;
- FormatSVNData(SC);
- LDumpLn(SC);
- end;
- CellEnd;
- end;
- RowNext;
- CellStart;
- DumpLn('Submitter:');
- CellNext;
- DumpLn(Q1.FieldByName('TU_SUBMITTER').AsString);
- CellNext;
+ SC:=Q1.FieldByName('svnrev').AsString;
+ if (SC<>'') then
+ FormatSVNData(SC);
if Q2 <> nil then
- DumpLn(Q2.FieldByName('TU_SUBMITTER').AsString);
- CellEnd;
- RowNext;
- CellStart;
- DumpLn('Date:');
- CellNext;
- F := Q1.FieldByName('TU_DATE');
- Date1 := F.AsDateTime;
- DumpLn(F.AsString);
- F := Q1.FieldByName('TU_COMPILERDATE');
+ begin
+ FRight:=Q2.FieldByName('svnrev').AsString;
+ FormatSVNData(FRight);
+ end
+ else
+ FRight:='';
+ EmitOneRow('SVN revisions:',SC,FRight);
+ end;
+ EmitRow('Submitter:','TU_SUBMITTER');
+ F := Q1.FieldByName('TU_DATE');
+ Date1 := F.AsDateTime;
+ SC:=F.AsString;
+ F := Q1.FieldByName('TU_COMPILERDATE');
+ Try
+ CompilerDate1 := F.AsDateTime;
+ if not SameDate(Date1,CompilerDate1) then
+ SC:=SC+' <> '+F.AsString;
+ Except
+ { Not a valid date, do nothing }
+ end;
+ if Q2 = nil then
+ FRight:=''
+ else
+ begin
+ F := Q2.FieldByName('TU_DATE');
+ Date2 := F.AsDateTime;
+ FRight:= F.AsString;
+ F := Q2.FieldByName('TU_COMPILERDATE');
Try
- CompilerDate1 := F.AsDateTime;
- if not SameDate(Date1,CompilerDate1) then
- DumpLn(' <> '+F.AsString);
+ CompilerDate2 := F.AsDateTime;
+ if not SameDate(Date2,CompilerDate2) then
+ FRight:=FRight+' <> '+F.AsString;
Except
{ Not a valid date, do nothing }
end;
- CellNext;
- if Q2 <> nil then
- begin
- F := Q2.FieldByName('TU_DATE');
- Date2 := F.AsDateTime;
- DumpLn(F.AsString);
- F := Q2.FieldByName('TU_COMPILERDATE');
- Try
- CompilerDate2 := F.AsDateTime;
- if not SameDate(Date2,CompilerDate2) then
- DumpLn(' <> '+F.AsString);
- Except
- { Not a valid date, do nothing }
- end;
- end;
- CellEnd;
- RowNext;
- CellStart;
- DumpLn('Previous run:');
- CellNext;
- FPreviousRunID:=GetPreviousRunID(FRunID);
- if FPreviousRunID<>'' then
- EmitHiddenVar('previousrunid',FPreviousRunID);
- DumpLn(FPreviousRunID);
- CellNext;
- if (FCompareRunID<>'') then
- begin
- FPrevious2RunID:=GetPreviousRunID(FCompareRunID);
- DumpLn(FPrevious2RunID);
- if FPrevious2RunID <> '' then
- EmitHiddenVar('previous2runid',FPrevious2RunID);
- end;
- CellEnd;
- RowNext;
- CellStart;
- DumpLn('Next run:');
- CellNext;
- FNextRunID:=GetNextRunID(FRunID);
- if FNextRunID<>'' then
- EmitHiddenVar('nextrunid',FNextRunID);
- DumpLn(FNextRunID);
- CellNext;
- if (FCompareRunID<>'') then
- begin
- FNext2RunID:=GetNextRunID(FCompareRunID);
- DumpLn(FNext2RunID);
- if FNext2RunID <> '' then
- EmitHiddenVar('next2runid',FNext2RunID);
- end;
- CellEnd;
+ end;
+ same_date:=(Copy(SC,1,10)=Copy(FRight,1,10));
+ EmitOneRow('Date:',SC,FRight,same_date);
+ FPreviousRunID:=GetPreviousRunID(FRunID);
+ if FPreviousRunID<>'' then
+ EmitHiddenVar('previousrunid',FPreviousRunID);
+ SC:=FPreviousRunID;
+ if (FCompareRunID<>'') then
+ begin
+ FPrevious2RunID:=GetPreviousRunID(FCompareRunID);
+ FRight:=FPrevious2RunID;
+ if FPrevious2RunID <> '' then
+ EmitHiddenVar('previous2runid',FPrevious2RunID);
+ end
+ else
+ FRight:='';
+ EmitOneRow('Previous run:',SC,FRight);
+ FNextRunID:=GetNextRunID(FRunID);
+ if FNextRunID<>'' then
+ EmitHiddenVar('nextrunid',FNextRunID);
+ SC:=FNextRunID;
+ if (FCompareRunID<>'') then
+ begin
+ FNext2RunID:=GetNextRunID(FCompareRunID);
+ FRight:=FNext2RunID;
+ if FNext2RunID <> '' then
+ EmitHiddenVar('next2runid',FNext2RunID);
+ end;
+ EmitOneRow('Next run:',SC,FRight);
RowEnd;
TableEnd;
ParagraphStart;
@@ -1397,7 +1401,22 @@ begin
ParaGraphStart;
end;
- EmitSubmitButton('action','Show/Compare');
+ if (FPrevious2RunID<>'') and (FPreviousRunId<>'') then
+ begin
+ EmitSubmitButton('action','Compare_both_to_previous');
+ AddNewPar:=true;
+ end;
+ if (FNext2RunID<>'') and (FNextRunId<>'') then
+ begin
+ EmitSubmitButton('action','Compare_both_to_next');
+ AddNewPar:=true;
+ end;
+ if AddNewPar then
+ begin
+ ParagraphEnd;
+ ParaGraphStart;
+ end;
+ EmitSubmitButton('action','Show/Compare');
if FTestFileID<>'' then
EmitSubmitButton('action','View_history');
EmitResetButton('','Reset form');
@@ -1524,7 +1543,7 @@ begin
finally
Free;
end;
- If Not (FRunCount=0) and not (FNoSkipped or FOnlyFailed) then
+ If Not (FRunCount=0) and not (FNoSkipped and FOnlyFailed) then
begin
ParaGraphStart;
TagStart('IMG',Format('Src="'+TestsuiteCGIURL+
@@ -2916,10 +2935,6 @@ Procedure TTestSuite.DoDrawPie(Img : TFPCustomImage; Skipped,Failed,Total : Inte
Var
Cnv : TFPImageCanvas;
- W,H,FH,CR,ra : Integer;
- A1,A2,FR,SR,PR : Double;
- R : TRect;
- F : TFreeTypeFont;
Procedure AddPie(X,Y,R : Integer; AStart,AStop : Double; Col : TFPColor);
@@ -2927,14 +2942,14 @@ Var
DX,Dy : Integer;
begin
- DX:=Round(R*Cos(A1));
- DY:=Round(R*Sin(A1));
+ DX:=Round(R*Cos(AStart));
+ DY:=Round(R*Sin(AStart));
Cnv.Line(X,Y,X+DX,Y-DY);
- DX:=Round(Ra*Cos(A2));
- DY:=Round(Ra*Sin(A2));
+ DX:=Round(R*Cos(AStop));
+ DY:=Round(R*Sin(AStop));
Cnv.Line(X,Y,X+DX,Y-Dy);
- DX:=Round(R/2*Cos((A1+A2)/2));
- DY:=Round(R/2*Sin((A1+A2)/2));
+ DX:=Round(R/2*Cos((AStart+AStop)/2));
+ DY:=Round(R/2*Sin((AStart+AStop)/2));
Cnv.Brush.FpColor:=Col;
Cnv.FloodFill(X+DX,Y-DY);
end;
@@ -2945,7 +2960,11 @@ Var
Result:=(2*Pi*(F/T))
end;
-
+Var
+ W,H,FH,CR,RA : Integer;
+ A1,A2,FR,SR,PR : Double;
+ R : TRect;
+ F : TFreeTypeFont;
begin
F:=TFreeTypeFont.Create;
@@ -3010,7 +3029,12 @@ begin
Writeln(stdout,'Setting brush style');
system.flush(stdout);
end;
- cnv.brush.FPColor:=colRed;
+ cnv.brush.FPColor:=colDkGray;
+ SR:=Skipped/Total;
+ FR:=Failed/Total;
+ PR:=1-SR-FR;
+ cnv.font.FPColor:=colDkGray;
+ Cnv.Textout(1,FH*2,Format('%d Skipped (%3.1f%%)',[Skipped,SR*100]));
// cnv.pen.width:=1;
// Writeln('Drawing ellipse');
Cnv.Ellipse(R);
@@ -3019,15 +3043,16 @@ begin
Writeln(stdout,'Setting text');
system.flush(stdout);
end;
- Cnv.Textout(1,FH*2,Format('%d Skipped (%3.1f%%)',[Skipped,SR*100]));
- A1:=(Pi*2*(failed/total));
- A2:=A1+(Pi*2*(Skipped/Total));
- AddPie(Ra,R.Top+Ra,Ra,A1,A2,ColYellow);
+ A1:=0;
+ A2:=A1+FractionAngle(Failed,Total);
+ cnv.font.FPColor:=colRed;
+ Cnv.Textout(1,FH*3,Format('%d Failed (%3.1f%%)',[Failed,FR*100]));
+ AddPie(Ra,R.Top+Ra,Ra,A1,A2,ColRed);
cnv.font.FPColor:=colGreen;
+ Cnv.Textout(1,FH,Format('%d Passed (%3.1f%%)',[Total-Skipped-Failed,PR*100]));
// Writeln('Palette size : ',Img.Palette.Count);
A1:=A2;
- A2:=A1+(Pi*2*((Total-(Skipped+Failed))/Total));
- Cnv.Textout(1,FH*3,Format('%d Passed (%3.1f%%',[Total-Skipped-Failed,PR*100]));
+ A2:=A1+FractionAngle(Total-(Skipped+Failed),Total);
AddPie(Ra,R.Top+Ra,Ra,A1,A2,ColGreen);
// Writeln('Palette size : ',Img.Palette.Count);
// Writeln('All done');
diff --git a/avx512-0037785/tests/webtbf/tw24434.pp b/avx512-0037785/tests/webtbf/tw24434.pp
new file mode 100644
index 0000000000..666655b0f8
--- /dev/null
+++ b/avx512-0037785/tests/webtbf/tw24434.pp
@@ -0,0 +1,13 @@
+{ %fail }
+function f(s: string): string;
+begin
+ f := '''' + s + '''';
+end;
+
+function f(s: string): integer;
+begin
+ Val(s,f);
+end;
+
+begin
+end.
diff --git a/avx512-0037785/tests/webtbf/tw37217.pp b/avx512-0037785/tests/webtbf/tw37217.pp
new file mode 100644
index 0000000000..b2969f3353
--- /dev/null
+++ b/avx512-0037785/tests/webtbf/tw37217.pp
@@ -0,0 +1,12 @@
+{ %fail }
+{$mode delphi}
+type
+ TEagle = class
+ constructor Create<Y>();
+ end;
+
+constructor TEagle.Create<Y>();
+begin
+end;
+begin
+end.
diff --git a/avx512-0037785/tests/webtbf/tw38287.pp b/avx512-0037785/tests/webtbf/tw38287.pp
new file mode 100644
index 0000000000..6971257653
--- /dev/null
+++ b/avx512-0037785/tests/webtbf/tw38287.pp
@@ -0,0 +1,11 @@
+{$macro on}
+var
+ a,b,s : real;
+
+begin
+ a:=1;
+ b:=2;
+{$define sum:=a+b }
+{$define b:=sum} { DON’T do this !!!}
+ s:=sum; { Will be infinitely recursively expanded... }
+end.
diff --git a/avx512-0037785/tests/webtbs/tw32139.pp b/avx512-0037785/tests/webtbs/tw32139.pp
new file mode 100644
index 0000000000..ced0f60db1
--- /dev/null
+++ b/avx512-0037785/tests/webtbs/tw32139.pp
@@ -0,0 +1,11 @@
+{ %OPT=-Seh }
+program Test;
+
+{$HINTS ON}
+
+var
+ cur: Currency;
+begin
+ cur := 3.5;
+ cur := cur / 1.5;
+end.
diff --git a/avx512-0037785/tests/webtbs/tw34027.pp b/avx512-0037785/tests/webtbs/tw34027.pp
new file mode 100644
index 0000000000..feacc2e199
--- /dev/null
+++ b/avx512-0037785/tests/webtbs/tw34027.pp
@@ -0,0 +1,27 @@
+uses
+ strings;
+
+type tz = record
+ name : pchar;
+ end;
+const aa :array[0..2] of char = 'aa'#0;
+
+const testArrZ : array [0..4] of tz = (
+ (name: @aa), { Ok }
+ (name: pchar(@aa)), { Ok }
+ (name: pchar(@aa)+1),
+ (name: pchar(@aa)+1+1),
+ (name: pchar(@aa)+1+1-1)
+ );
+
+var b : pchar;
+
+begin
+ b:=pchar(@aa)+1; {Ok}
+ if strlen(testArrZ[2].name)<>1 then
+ halt(1);
+ if strlen(testArrZ[3].name)<>0 then
+ halt(2);
+ if strlen(testArrZ[4].name)<>1 then
+ halt(2);
+end.
diff --git a/avx512-0037785/tests/webtbs/tw37060.pp b/avx512-0037785/tests/webtbs/tw37060.pp
index c167a50887..847c5ede4f 100644
--- a/avx512-0037785/tests/webtbs/tw37060.pp
+++ b/avx512-0037785/tests/webtbs/tw37060.pp
@@ -4,7 +4,7 @@ program fp37060;
uses sockets, Classes, SysUtils;
-procedure BuildBadAddrs4(out bad_addrs: TStringList);
+procedure BuildBadAddrs4(var bad_addrs: TStringList);
begin
bad_addrs.Add('1.1.1.1.1'); // too many octets
bad_addrs.Add('0xa.3.4.5'); //hex in octets
@@ -32,7 +32,7 @@ begin
bad_addrs.Add('&7.&5.30.4'); // octal
end;
-procedure BuildGoodAddrs4(out good_addrs: TStringList);
+procedure BuildGoodAddrs4(var good_addrs: TStringList);
begin
good_addrs.Add('127.0.0.1|127.0.0.1');
good_addrs.Add('0.0.0.0|0.0.0.0');
@@ -40,7 +40,7 @@ begin
good_addrs.Add('255.255.255.255|255.255.255.255');
end;
-procedure BuildBadAddrs6(out bad_addrs: TStringList);
+procedure BuildBadAddrs6(var bad_addrs: TStringList);
begin
// start with some obviously bad formats.
bad_addrs.Add('');
@@ -193,7 +193,7 @@ begin
bad_addrs.Add('127.0.0.2');
end;
-procedure BuildGoodAddrs6(out addrlist: TStringList);
+procedure BuildGoodAddrs6(var addrlist: TStringList);
begin
// Each str is two parts, separated by a pipe. The left part is the input
// address to be parsed, and the right is the expected result of taking the
diff --git a/avx512-0037785/tests/webtbs/tw38306.pp b/avx512-0037785/tests/webtbs/tw38306.pp
new file mode 100644
index 0000000000..1fbcea7a38
--- /dev/null
+++ b/avx512-0037785/tests/webtbs/tw38306.pp
@@ -0,0 +1,39 @@
+{ %OPT=-gh }
+{$mode objfpc}
+program gqueue_test;
+
+uses
+ gqueue;
+
+type
+ TIntQueue = specialize TQueue<Integer>;
+
+var
+ IntQueue: TIntQueue;
+ PushCnt: Integer;
+
+procedure Push2Pop1;
+var
+ i: Integer;
+begin
+ for i:= 0 to 1000000 do begin
+ IntQueue.Push(PushCnt);
+ inc(PushCnt);
+ IntQueue.Push(PushCnt);
+ inc(PushCnt);
+ IntQueue.Pop();
+ end;
+end;
+
+var
+ i: Integer;
+begin
+ try
+ IntQueue:= TIntQueue.Create;
+ Push2Pop1;
+ WriteLn('Ready');
+ finally
+ IntQueue.Free;
+ end;
+end.
+
diff --git a/avx512-0037785/tests/webtbs/tw38316.pp b/avx512-0037785/tests/webtbs/tw38316.pp
new file mode 100644
index 0000000000..29cd58b0e7
--- /dev/null
+++ b/avx512-0037785/tests/webtbs/tw38316.pp
@@ -0,0 +1,21 @@
+{ %opt=-gh }
+
+program project1;
+
+procedure P1(A: array of Integer);
+begin
+end;
+
+procedure P2(A: array of Integer);
+begin
+ P1(A);
+end;
+
+var
+ A: array [0..2] of Integer;
+ i: Integer;
+begin
+ HaltOnNotReleased := true;
+ for i := 0 to 10 do
+ P2(A);
+end.
diff --git a/avx512-0037785/tests/webtbs/tw38337.pp b/avx512-0037785/tests/webtbs/tw38337.pp
new file mode 100644
index 0000000000..7d461ddfa9
--- /dev/null
+++ b/avx512-0037785/tests/webtbs/tw38337.pp
@@ -0,0 +1,20 @@
+program fs;
+
+{$mode objfpc}{$H+}
+
+function UTF8Length(const s: string): PtrInt; inline;
+begin
+ Result:=9;
+end;
+
+
+var
+ v1: string;
+ s: shortstring;
+ i: Integer;
+begin
+ v1 := '123456789';
+ s := v1;
+ for i := 1 to UTF8Length(s)-8 do begin
+ end;
+end.
diff --git a/avx512-0037785/tests/webtbs/tw38339.pp b/avx512-0037785/tests/webtbs/tw38339.pp
new file mode 100644
index 0000000000..e81db9c9da
--- /dev/null
+++ b/avx512-0037785/tests/webtbs/tw38339.pp
@@ -0,0 +1,23 @@
+{%OPT=-O3 }
+program test48086;
+{$mode objfpc}{$H+}
+function IsFontNameXLogicalFontDesc(const LongFontName: string): boolean;
+var MinusCnt, p: integer;
+begin
+ MinusCnt:=0;
+ for p:=1 to length(LongFontName) do
+ if LongFontName[p]='-' then inc(MinusCnt);
+ Result:=(MinusCnt=14);
+end;
+var
+myfont:string;
+begin
+ myfont:='Myfont--------------';
+ if IsFontNameXLogicalFontDesc(myfont) then
+ writeln('NO ERROR')
+ else
+ begin
+ writeln('Error in count');
+ halt(1);
+ end;
+end.
diff --git a/avx512-0037785/tests/webtbs/tw38351.pp b/avx512-0037785/tests/webtbs/tw38351.pp
new file mode 100644
index 0000000000..d76d639b4c
--- /dev/null
+++ b/avx512-0037785/tests/webtbs/tw38351.pp
@@ -0,0 +1,33 @@
+{$MODE OBJFPC}
+{$APPTYPE CONSOLE}
+
+uses Classes, BufStream, Sysutils;
+
+procedure TestBufferedFileStream;
+var
+ F: TStream;
+ pf: File;
+begin
+ Assign(pf,'tw38351.tmp');
+ Rewrite(pf,1);
+ Seek(pf,100);
+ Close(pf);
+ F := TBufferedFileStream.Create('tw38351.tmp', fmOpenRead);
+ try
+ Writeln(F.Position);
+ if F.Position<>0 then
+ halt(1);
+ Writeln(F.Seek(0, soBeginning)); // TFileStream = 0, TBufferedFileStream = -1
+ Writeln(F.Position);
+ if F.Position<>0 then
+ halt(1);
+ finally
+ F.Free;
+ DeleteFile('tw38351.tmp');
+ end;
+end;
+
+begin
+ TestBufferedFileStream;
+ writeln('ok');
+end.
diff --git a/avx512-0037785/tests/webtbs/tw38385.pp b/avx512-0037785/tests/webtbs/tw38385.pp
new file mode 100644
index 0000000000..30a66965a2
--- /dev/null
+++ b/avx512-0037785/tests/webtbs/tw38385.pp
@@ -0,0 +1,41 @@
+{ %norun }
+Unit tw38385;
+
+{$mode objfpc}{$H+}
+
+Interface
+
+Uses
+ uw38385a, uw38385b, uw38385c;
+
+Type
+
+ { TFoo }
+
+ TFoo = Class(TInterfacedObject, uw38385a.IInterface1, uw38385b.IInterface1, uw38385c.IInterface1)
+ Procedure p1();
+ Procedure p2();
+ Procedure p3();
+ End;
+
+Implementation
+
+{ TFoo }
+
+Procedure TFoo.p1();
+Begin
+ WriteLn('p1');
+End;
+
+Procedure TFoo.p2();
+Begin
+ WriteLn('p2');
+End;
+
+Procedure TFoo.p3();
+Begin
+ WriteLn('p3');
+End;
+
+End.
+
diff --git a/avx512-0037785/tests/webtbs/tw38390.pp b/avx512-0037785/tests/webtbs/tw38390.pp
new file mode 100644
index 0000000000..11a2c523b0
--- /dev/null
+++ b/avx512-0037785/tests/webtbs/tw38390.pp
@@ -0,0 +1,23 @@
+program tw38390;
+{$MODE Delphi}
+uses SysUtils;
+
+var
+ s: String;
+ x: UInt64;
+
+begin
+ s := '20000000000';
+ x := UInt64.Parse(s);
+ WriteLn(x);
+ if x <> 20000000000 then
+ Halt(1);
+ UInt64.TryParse(s, x);
+ WriteLn(x);
+ if x <> 20000000000 then
+ Halt(2);
+ x := StrToQWord(s);
+ WriteLn(x);
+ if x <> 20000000000 then
+ Halt(3);
+end.
diff --git a/avx512-0037785/tests/webtbs/tw38412.pp b/avx512-0037785/tests/webtbs/tw38412.pp
new file mode 100644
index 0000000000..dcfe911a99
--- /dev/null
+++ b/avx512-0037785/tests/webtbs/tw38412.pp
@@ -0,0 +1,10 @@
+{ %norun }
+type
+ measure = (short := 1, long := 2);
+ generic bar<const x: measure> = object
+ public
+ const
+ myMeasure = ord(x);
+ end;
+begin
+end.
diff --git a/avx512-0037785/tests/webtbs/tw38413.pp b/avx512-0037785/tests/webtbs/tw38413.pp
new file mode 100644
index 0000000000..ccd5930eac
--- /dev/null
+++ b/avx512-0037785/tests/webtbs/tw38413.pp
@@ -0,0 +1,12 @@
+var
+ arr : array[-1..140] of byte=(4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4);
+ index , value : byte; // unsigned byte - important
+begin
+ index:=133; // positive value, which is treated as negative
+ value:=arr[index]; // wrong value! Memory access outside array
+ if value<>4 then
+ halt(1);
+ writeln('ok');
+end.
diff --git a/avx512-0037785/tests/webtbs/tw38429.pp b/avx512-0037785/tests/webtbs/tw38429.pp
new file mode 100644
index 0000000000..87e9c9913e
--- /dev/null
+++ b/avx512-0037785/tests/webtbs/tw38429.pp
@@ -0,0 +1,61 @@
+program tw38429;
+
+{$mode objfpc}{$h+}
+
+uses
+ SysUtils, Variants, uw38429;
+
+var
+ v, d: Variant;
+ I: Integer = 42;
+begin
+ Writeln('Test VarAsType');
+ d := I;
+ try
+ v := VarAsType(d, varMyVar);
+ except
+ on e: exception do begin
+ WriteLn('cast ', VarTypeAsText(VarType(d)), ' to ',VarTypeAsText(varMyVar),
+ ' raises ', e.ClassName, ' with message: ', e.Message);
+ Halt(1);
+ end;
+ end;
+ WriteLn('now v is ', VarTypeAsText(VarType(v)));
+ VarClear(d);
+ try
+ d := VarAsType(v, varInteger);
+ except
+ on e: exception do begin
+ WriteLn('cast ', VarTypeAsText(VarType(v)), ' to ',VarTypeAsText(varInteger),
+ ' raises ', e.ClassName, ' with message: ', e.Message);
+ Halt(2);
+ end;
+ end;
+ WriteLn('now d is ', VarTypeAsText(VarType(d)));
+
+ { also test VarCast from #20849 }
+ Writeln('Test VarCast');
+ d := I;
+ try
+ VarCast(v, d, varMyVar);
+ except
+ on e: exception do begin
+ WriteLn('cast ', VarTypeAsText(VarType(d)), ' to ',VarTypeAsText(varMyVar),
+ ' raises ', e.ClassName, ' with message: ', e.Message);
+ Halt(3);
+ end;
+ end;
+ WriteLn('now v is ', VarTypeAsText(VarType(v)));
+ VarClear(d);
+ try
+ VarCast(d, v, varInteger);
+ except
+ on e: exception do begin
+ WriteLn('cast ', VarTypeAsText(VarType(v)), ' to ',VarTypeAsText(varInteger),
+ ' raises ', e.ClassName, ' with message: ', e.Message);
+ Halt(4);
+ end;
+ end;
+ WriteLn('now d is ', VarTypeAsText(VarType(d)));
+end.
+
diff --git a/avx512-0037785/tests/webtbs/uw38385a.pp b/avx512-0037785/tests/webtbs/uw38385a.pp
new file mode 100644
index 0000000000..41110fc8a8
--- /dev/null
+++ b/avx512-0037785/tests/webtbs/uw38385a.pp
@@ -0,0 +1,17 @@
+Unit uw38385a;
+
+{$mode objfpc}{$H+}
+
+Interface
+
+Type
+ IInterface1 = Interface(IInterface)
+ Procedure p1();
+ End;
+
+Implementation
+
+
+
+End.
+
diff --git a/avx512-0037785/tests/webtbs/uw38385b.pp b/avx512-0037785/tests/webtbs/uw38385b.pp
new file mode 100644
index 0000000000..a4b5d9eca7
--- /dev/null
+++ b/avx512-0037785/tests/webtbs/uw38385b.pp
@@ -0,0 +1,18 @@
+unit uw38385b;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ uw38385a;
+
+type
+ IInterface1 = Interface(uw38385a.IInterface1)
+ Procedure p2();
+ End;
+
+implementation
+
+end.
+
diff --git a/avx512-0037785/tests/webtbs/uw38385c.pp b/avx512-0037785/tests/webtbs/uw38385c.pp
new file mode 100644
index 0000000000..069d50f7f4
--- /dev/null
+++ b/avx512-0037785/tests/webtbs/uw38385c.pp
@@ -0,0 +1,18 @@
+Unit uw38385c;
+
+{$mode objfpc}{$H+}
+
+Interface
+
+Uses
+ uw38385a;
+
+Type
+ IInterface1 = Interface(uw38385a.IInterface1)
+ Procedure p3();
+ End;
+
+Implementation
+
+End.
+
diff --git a/avx512-0037785/tests/webtbs/uw38429.pp b/avx512-0037785/tests/webtbs/uw38429.pp
new file mode 100644
index 0000000000..0ec87fb766
--- /dev/null
+++ b/avx512-0037785/tests/webtbs/uw38429.pp
@@ -0,0 +1,88 @@
+unit uw38429;
+
+{$mode objfpc}{$H+}
+{$modeswitch advancedrecords}
+
+interface
+
+uses
+ SysUtils, Variants;
+
+type
+ TMyVar = packed record
+ VType: TVarType;
+ Dummy1: array[0..2] of Word;
+ Dummy2,
+ Dummy3: Pointer;
+ procedure Init;
+ end;
+
+ { TMyVariant }
+
+ TMyVariant = class(TInvokeableVariantType)
+ procedure Copy(var Dest: TVarData; const Source: TVarData; const Indirect: Boolean); override;
+ procedure Clear(var V: TVarData); override;
+ procedure Cast(var Dest: TVarData; const Source: TVarData); override;
+ procedure CastTo(var Dest: TVarData; const Source: TVarData; const aVarType: TVarType); override;
+ end;
+
+ function MyVarCreate: Variant;
+
+ function varMyVar: TVarType;
+
+implementation
+
+var
+ MyVariant: TMyVariant;
+
+function MyVarCreate: Variant;
+begin
+ VarClear(Result);
+ TMyVar(Result).Init;
+end;
+
+function VarMyVar: TVarType;
+begin
+ Result := MyVariant.VarType;
+end;
+
+{ TMyVar }
+
+procedure TMyVar.Init;
+begin
+ VType := VarMyVar;
+end;
+
+{ TMyVariant }
+
+procedure TMyVariant.Copy(var Dest: TVarData; const Source: TVarData;
+ const Indirect: Boolean);
+begin
+ Dest := Source;
+end;
+
+procedure TMyVariant.Clear(var V: TVarData);
+begin
+ TMyVar(v).VType := varEmpty;
+end;
+
+procedure TMyVariant.Cast(var Dest: TVarData; const Source: TVarData);
+begin
+ WriteLn('TMyVariant.Cast');
+ VarClear(Variant(Dest));
+ TMyVar(Dest).Init;
+end;
+
+procedure TMyVariant.CastTo(var Dest: TVarData; const Source: TVarData; const aVarType: TVarType);
+begin
+ WriteLn('TMyVariant.CastTo');
+ VarClear(Variant(Dest));
+ TVarData(Dest).VType := aVarType;
+end;
+
+initialization
+ MyVariant := TMyVariant.Create;
+finalization
+ MyVariant.Free;
+end.
+
diff --git a/avx512-0037785/utils/fpdoc/dglobals.pp b/avx512-0037785/utils/fpdoc/dglobals.pp
index 2cfed6aed8..c2bd23dd97 100644
--- a/avx512-0037785/utils/fpdoc/dglobals.pp
+++ b/avx512-0037785/utils/fpdoc/dglobals.pp
@@ -33,203 +33,6 @@ Var
LEOL : Integer;
modir : string;
-resourcestring
- // Output strings
- SDocPackageTitle = 'Reference for package ''%s''';
- SDocPackageMenuTitle = 'Package ''%s''';
- SDocPackageLinkTitle = 'Package';
- SDocPrograms = 'Programs';
- SDocUnits = 'Units';
- SDocUnitTitle = 'Reference for unit ''%s''';
- SDocUnitMenuTitle = 'Unit ''%s''';
- SDocInheritanceHierarchy = 'Inheritance Hierarchy';
- SDocInterfaceSection = 'Interface section';
- SDocImplementationSection = 'Implementation section';
- SDocUsedUnits = 'Used units';
- SDocUsedUnitsByUnitXY = 'Used units by unit ''%s''';
- SDocConstsTypesVars = 'Constants, types and variables';
- SDocResStrings = 'Resource strings';
- SDocTypes = 'Types';
- SDocType = 'Type';
- SDocConstants = 'Constants';
- SDocConstant = 'Constant';
- SDocClasses = 'Classes';
- SDocClass = 'Class';
- SDocProceduresAndFunctions = 'Procedures and functions';
- SDocProcedureOrFunction = 'Procedure/function';
- SDocVariables = 'Variables';
- SDocVariable = 'Variable';
- SDocIdentifierIndex = 'Index';
- SDocPackageClassHierarchy = 'Class hierarchy';
- SDocModuleIndex = 'Index of all identifiers in unit ''%s''';
- SDocPackageIndex = 'Index of all identifiers in package ''%s''';
- SDocUnitOverview = 'Overview of unit ''%s''';
- SDocOverview = 'Overview';
- SDocSearch = 'Search';
- SDocDeclaration = 'Declaration';
- SDocDescription = 'Description';
- SDocErrors = 'Errors';
- SDocVersion = 'Version info';
- SDocSeeAlso = 'See also';
- SDocExample = 'Example';
- SDocArguments = 'Arguments';
- SDocFunctionResult = 'Function result';
- SDocRemark = 'Remark: ';
- SDocMethodOverview = 'Method overview';
- SDocPropertyOverview = 'Property overview';
- SDocEventOverview = 'Event overview';
- SDocInterfacesOverview = 'Interfaces overview';
- SDocInterface = 'Interfaces';
- SDocPage = 'Page';
- SDocMember = 'Member';
- SDocMembers = 'Members';
- SDocField = 'Field';
- SDocMethod = 'Method';
- SDocProperty = 'Property';
- SDocAccess = 'Access';
- SDocInheritance = 'Inheritance';
- SDocProperties = 'Properties';
- SDocMethods = 'Methods';
- SDocEvents = 'Events';
- SDocByName = 'by Name';
- SDocByInheritance = 'By inheritance';
- SDocValue = 'Value';
- SDocExplanation = 'Explanation';
- SDocProcedure = 'Procedure';
- SDocValuesForEnum = 'Enumeration values for type %s';
- SDocSourcePosition = 'Source position: %s line %d';
- SDocSynopsis = 'Synopsis';
- SDocVisibility = 'Visibility';
- SDocOpaque = 'Opaque type';
- SDocDateGenerated = 'Documentation generated on: %s';
- // The next line requires leading/trailing space due to XML comment layout:
- SDocGeneratedByComment = ' Generated using FPDoc - (c) 2000-2012 FPC contributors and Sebastian Guenther, sg@freepascal.org ';
- SDocNotes = 'Notes';
- SDocName = 'Name';
- SDocType_s = 'Type(s)';
- SDocTopic = 'Topic';
- SDocNoneAVailable = 'No members available';
-
- // Topics
- SDocRelatedTopics = 'Related topics';
- SDocUp = 'Up';
- SDocNext = 'Next';
- SDocPrevious = 'Previous';
-
- // Various backend constants
- SDocChapter = 'Chapter';
- SDocSection = 'Section';
- SDocSubSection = 'Subsection';
- SDocTable = 'Table';
- SDocListing = 'Listing';
-
- // Man page usage
- SManUsageManSection = 'Use ASection as the man page section';
- SManUsageNoUnitPrefix = 'Do not prefix man pages with unit name.';
- SManUsageWriterDescr = 'UNIX man page output.';
- SManUsagePackageDescription = 'Use descr as the description of man pages';
-
- // HTML usage
- SHTMLUsageFooter = 'Append xhtml (@filename reads from file) as footer to html page';
- SHTMLUsageNavigator = 'Append xhtml (@filename reads from file) in navigator bar';
- SHTMLUsageHeader = 'Append xhtml (@filename reads from file) as header to html page below navigation bar';
- SHTMLUsageFooterDate = 'Append footer with date. fmt is Optional format for FormatDateTime';
- SHTMLUsageCharset = 'Set the HTML character set';
- SHTMLHtmlSearch = 'Add search page with given name to the menu bar';
- SHTMLIndexColcount = 'Use N columns in the identifier index pages';
- SHTMLImageUrl = 'Prefix image URLs with url';
- SHTMLDisableMenuBrackets = 'Disable ''['' and '']'' characters around menu items at the top of the page. Useful for custom css';
-
- // CHM usage
- SCHMUsageTOC = 'Use [File] as the table of contents. Usually a .hhc file.';
- SCHMUsageIndex = 'Use [File] as the index. Usually a .hhk file.';
- SCHMUsageDefPage = 'Set the "Home" page relative to where it lives in the chm. i.e. "/index.html"';
- SCHMUsageOtrFiles= 'A txt file containing a list of files to be added relative to the working directory.';
- SCHMUsageCSSFile = 'Filename of a .css file to be included in the chm.';
- SCHMUsageAutoTOC = 'Automatically generate a Table of Contents. Ignores --toc-file';
- SCHMUsageAutoIDX = 'Automatically generate an Index. Ignores --index-file';
- SCHMUsageMakeSearch = 'Automatically generate a Search Index from filenames that match *.htm*';
- SCHMUsageChmTitle= 'Title of the chm. Defaults to the value from --package';
-
- // MarkDown usage
- SMDUsageFooter = 'Append markdown (@filename reads from file) as footer to every markdown page';
- SMDUsageHeader = 'Prepend markdown (@filename reads from file) as header to every markdown page';
- SMDIndexColcount = 'Use N columns in the identifier index pages';
- SMDImageUrl = 'Prefix image URLs with url';
- SMDTheme = 'Use name as theme name';
- SMDNavigation = 'Use scheme for navigation tree, here scheme is one of:';
- SMDNavSubtree = ' UnitSubTree : put all units in a sub tree of a Units node';
- SMDNavTree = ' UnitTree : put every units as a node on the same level as packages node';
-
- SXMLUsageFlatStructure = 'Use a flat output structure of XML files and directories';
- SXMLUsageSource = 'Include source file and line info in generated XML';
-
- // Linear usage
- SLinearUsageDupLinkedDocsP1 = 'Duplicate linked element documentation in';
- SLinearUsageDupLinkedDocsP2 = 'descendant classes.';
-
- STitle = 'FPDoc - Free Pascal Documentation Tool';
- SVersion = 'Version %s [%s]';
- SCopyright1 = '(c) 2000 - 2003 Areca Systems GmbH / Sebastian Guenther, sg@freepascal.org';
- SCopyright2 = '(c) 2005 - 2021 various FPC contributors';
-
- SCmdLineHelp = 'Usage: %s [options]';
- SUsageOption008 = '--base-descr-dir=DIR prefix all description files with this directory';
- SUsageOption009 = '--base-input-dir=DIR prefix all input files with this directory';
- SUsageOption010 = '--content Create content file for package cross-references';
- SUsageOption020 = '--cputarget=value Set the target CPU for the scanner.';
- SUsageOption030 = '--descr=file use file as description file, e.g.: ';
- SUsageOption035 = ' --descr=c:\WIP\myzipperdoc.xml';
- SUsageOption040 = ' This option is allowed more than once';
- SUsageOption050 = '--descr-dir=Dir Add All XML files in Dir to list of description files';
- SUsageOption060 = '--format=fmt Select output format.';
- SUsageOption070 = '--help Show this help.';
- SUsageOption080 = '--hide-protected Do not show protected methods in overview';
- SUsageOption090 = '--import=file Import content file for package cross-references';
- SUsageOption100 = '--input=cmd use cmd as input for the parser, e.g.:';
- SUsageOption110 = ' --input=C:\fpc\packages\paszlib\src\zipper.pp';
- SUsageOption120 = ' At least one input option is required.';
- SUsageOption130 = '--input-dir=Dir Add All *.pp and *.pas files in Dir to list of input files';
- SUsageOption140 = '--lang=lng Select output language.';
- SUsageOption145 = '--macro=name=value Define a macro to preprocess the project file with.';
- SUsageOption150 = '--ostarget=value Set the target OS for the scanner.';
- SUsageOption160 = '--output=name use name as the output name.';
- SUsageOption170 = ' Each backend interprets this as needed.';
- SUsageOption180 = '--package=name Set the package name for which to create output,';
- SUsageOption190 = ' e.g. --package=fcl';
- SUsageOption200 = '--project=file Use file as project file';
- SUsageOption210 = '--show-private Show private methods.';
- SUsageOption215 = '--stop-on-parser-error';
- SUsageOption215A = ' Stop when a parser error occurs. Default is to ignore parser errors.';
- SUsageOption220 = '--warn-no-node Warn if no documentation node was found.';
- SUsageOption230 = '--mo-dir=dir Set directory where language files reside to dir';
- SUsageOption240 = '--parse-impl (Experimental) try to parse implementation too';
- SUsageOption250 = '--dont-trim Do not trim XML contents. Useful for preserving';
- SUsageOption260 = ' formatting inside e.g <pre> tags';
- SUsageOption270 = '--write-project=file';
- SUsageOption280 = ' Do not write documentation, create project file instead';
- SUsageOption290 = '--verbose Write more information on the screen';
- SUsageOption300 = '--dry-run Only parse sources and XML, do not create output';
- SUsageOption310 = '--write-project=file';
- SUsageOption320 = ' Write all command-line options to a project file';
- SUsageSubNames = 'Use the file subnames instead the indexes as postfixes';
-
- SUsageFormats = 'The following output formats are supported by this fpdoc:';
- SUsageBackendHelp = 'Specify an output format, combined with --help to get more help for this backend.';
- SUsageFormatSpecific = 'Output format "%s" supports the following options:';
- SCmdLineErrInvalidMacro = 'Macro needs to be in the form name=value';
-
- SCmdLineInvalidOption = 'Ignoring unknown option "%s"';
- SCmdLineInvalidFormat = 'Invalid format "%s" specified';
- SCmdLineOutputOptionMissing = 'Need an output filename, please specify one with --output=<filename>';
- SWritingPages = 'Writing %d pages...';
- SNeedPackageName = 'No package name specified. Please specify one using the --package option.';
- SAvailablePackages = 'Available packages: ';
- SDone = 'Done.';
- SErrCouldNotCreateOutputDir = 'Could not create output directory "%s"';
- SErrCouldNotCreateFile = 'Could not create file "%s": %s';
- SSeeURL = '(See %s)'; // For linear text writers.
- SParsingUsedUnit = 'Parsing used unit "%s" with commandLine "%s"';
Const
SVisibility: array[TPasMemberVisibility] of string =
@@ -335,7 +138,7 @@ type
// The main FPDoc engine
- TFPDocLogLevel = (dleWarnNoNode);
+ TFPDocLogLevel = (dleWarnNoNode, dleWarnUsedFile, dleDocumentationEmpty, dleXCT);
TFPDocLogLevels = set of TFPDocLogLevel;
TOnParseUnitEvent = Procedure (Sender : TObject; Const AUnitName : String; Out AInputFile,OSTarget,CPUTarget : String) of Object;
@@ -364,8 +167,7 @@ type
HasContentFile: Boolean;
HidePrivate: Boolean; // Hide private class members in output?
HideProtected: Boolean; // Hide protected class members in output?
- WarnNoNode : Boolean; // Warn if no description node found for element.
-
+ FalbackSeeAlsoLinks: Boolean; // Simplify SeeAlso Links
constructor Create;
destructor Destroy; override;
procedure SetPackageName(const APackageName: String);
@@ -378,7 +180,7 @@ type
AParent: TPasElement; AVisibility: TPasMemberVisibility;
const ASourceFilename: String; ASourceLinenumber: Integer): TPasElement;
override;
- function FindInModule(const AName: String ; AModule: TPasModule): TPasElement;
+ function FindElement(const AName: String ; AModule: TPasModule): TPasElement; overload;
function FindElement(const AName: String): TPasElement; override;
function FindModule(const AName: String): TPasModule; override;
Function HintsToStr(Hints : TPasMemberHints) : String;
@@ -386,6 +188,7 @@ type
// Link tree support
procedure AddLink(const APathName, ALinkTo: String);
function FindAbsoluteLink(const AName: String): String;
+ // resolve link inside actual AModule and AModule.Parent = APackage
function ResolveLink(AModule: TPasModule; const ALinkDest: String; Strict : Boolean = False): String;
function FindLinkedNode(ANode: TDocNode): TDocNode;
Function ShowElement(El : TPasElement) : Boolean; inline;
@@ -411,7 +214,9 @@ type
procedure TranslateDocStrings(const Lang: String);
+{$IFDEF EXCEPTION_STACK}
function DumpExceptionCallStack(E: Exception):String;
+{$ENDIF}
Function IsLinkNode(Node : TDomNode) : Boolean;
Function IsExampleNode(Example : TDomNode) : Boolean;
@@ -422,7 +227,7 @@ Function IsLinkAbsolute(ALink: String): boolean;
implementation
-uses Gettext, XMLRead;
+uses Gettext, XMLRead, fpdocstrs;
const
AbsoluteLinkPrefixes : array[0..2] of string = ('/', 'http://', 'ms-its:');
@@ -670,8 +475,11 @@ destructor TFPDocEngine.Destroy;
var
i: Integer;
begin
+ if FPackages.Count > 0 then
for i := 0 to FPackages.Count - 1 do
- TPasPackage(FPackages[i]).Release{$IFDEF CheckPasTreeRefCount}('TFPDocEngine.Destroy'){$ENDIF};
+ TPasPackage(FPackages[i]).Release{$IFDEF CheckPasTreeRefCount}('TFPDocEngine.Destroy'){$ENDIF}
+ else
+ FreeAndNil(FPackages);
FreeAndNil(FRootDocNode);
FreeAndNil(FRootLinkNode);
FreeAndNil(DescrDocNames);
@@ -910,7 +718,7 @@ var
end;
end
else
- if cls<>result then
+ if (dleXCT in FDocLogLevels) and (cls<>result) then
DoLog('Warning : ancestor class %s of class %s could not be resolved',[clname,cls.name]);
end;
@@ -970,7 +778,7 @@ var
if alname<>'' then // the class//interface we refered to is an alias
begin
// writeln('Found alias pair ',clname,' = ',alname);
- if not assigned(CreateAliasType(alname,clname,cls,cls2)) then
+ if (dleXCT in FDocLogLevels) and not assigned(CreateAliasType(alname,clname,cls,cls2)) then
DoLog('Warning: creating alias %s for %s failed!',[alname,clname]);
end
else
@@ -1217,7 +1025,7 @@ begin
Result.SourceLinenumber := ASourceLinenumber;
end;
-function TFPDocEngine.FindInModule ( const AName: String; AModule: TPasModule
+function TFPDocEngine.FindElement ( const AName: String; AModule: TPasModule
) : TPasElement;
var
l: TFPList;
@@ -1244,14 +1052,14 @@ var
i: Integer;
Module: TPasElement;
begin
- Result := FindInModule( AName, CurModule );
+ Result := FindElement( AName, CurModule );
if not Assigned(Result) and assigned (CurModule.InterfaceSection) then
for i := CurModule.InterfaceSection.UsesList.Count - 1 downto 0 do
begin
Module := TPasElement(CurModule.InterfaceSection.UsesList[i]);
if Module.ClassType.InheritsFrom(TPasModule) then
begin
- Result := FindInModule(AName, TPasModule(Module));
+ Result := FindElement(AName, TPasModule(Module));
if Assigned(Result) then
exit;
end;
@@ -1264,6 +1072,7 @@ function TFPDocEngine.FindModule(const AName: String): TPasModule;
var
i: Integer;
begin
+ if not Assigned(APackage) then Exit;
for i := 0 to APackage.Modules.Count - 1 do
begin
Result := TPasModule(APackage.Modules[i]);
@@ -1279,7 +1088,7 @@ var
begin
Result := FindInPackage(Package);
- if not Assigned(Result) then
+ if not Assigned(Result) and (FPackages.Count > 0) then
for i := FPackages.Count - 1 downto 0 do
begin
if TPasPackage(FPackages[i]) = Package then
@@ -1319,11 +1128,12 @@ Var
M : TPasModule;
begin
- DoLog(SParsingUsedUnit,[AName,AInputLine]);
+ if dleWarnUsedFile in FDocLogLevels then
+ DoLog(SParsingUsedUnit,[AName,AInputLine]);
M:=CurModule;
CurModule:=Nil;
try
- ParseSource(Self,AInputLine,AOSTarget,ACPUTarget,[poUseStreams,poSkipDefaultDefs]);
+ ParseSource(Self,AInputLine,AOSTarget,ACPUTarget,[poUseStreams]); //[poSkipDefaultDefs];
Result:=CurModule;
finally
CurModule:=M;
@@ -1382,7 +1192,6 @@ end;
function TFPDocEngine.ResolveLink(AModule: TPasModule; const ALinkDest: String; Strict : Boolean = False): String;
var
i: Integer;
-
begin
{
if Assigned(AModule) then
@@ -1393,14 +1202,18 @@ begin
if (ALinkDest='') then
Exit('');
if (ALinkDest[1] = '#') then
+ // Link has full path
Result := FindAbsoluteLink(ALinkDest)
else if (AModule=Nil) then
+ // Trying to add package name only
Result:= FindAbsoluteLink(RootLinkNode.FirstChild.Name+'.'+ALinkDest)
else
begin
- if Pos(AModule.Name,ALinkDest) = 1 then
+ if Pos(LowerCase(AModule.Name)+'.',LowerCase(ALinkDest)) = 1 then
+ // fix ERROR - Link starts from name of module
Result := ResolveLink(AModule, AModule.packagename + '.' + ALinkDest, Strict)
else
+ // Link should be a first level inside of module
Result := ResolveLink(AModule, AModule.PathName + '.' + ALinkDest, Strict);
if (Result='') then
begin
@@ -1411,12 +1224,17 @@ begin
end;
// Match on parent : class/enumerated/record/module
if (Result='') and not strict then
+ begin
+ // TODO: I didn't see a calling this code at entire lcl package
+ // Writeln('INFO UnStrinct(): ' + ALinkDest);
for i := Length(ALinkDest) downto 1 do
if ALinkDest[i] = '.' then
begin
Result := ResolveLink(AModule, Copy(ALinkDest, 1, i - 1), Strict);
+ //if Result <> '' then Writeln('INFO LinkResolved UnStrinct(): '+Result);
exit;
end;
+ end;
end;
procedure ReadXMLFileALT(OUT ADoc:TXMLDocument;const AFileName:ansistring);
@@ -1590,7 +1408,7 @@ begin
if aElement.CustomData=Nil then
aElement.CustomData:=Result;
end
- else if WarnNoNode and
+ else if (dleWarnNoNode in FDocLogLevels) and
(Length(AElement.PathName)>0) and
(AElement.PathName[1]='#') then
DoLog(Format('No documentation node found for identifier : %s',[AElement.PathName]));
@@ -1791,6 +1609,7 @@ begin
end;
end;
+{$IFDEF EXCEPTION_STACK}
function DumpExceptionCallStack(E: Exception):String;
var
I: Integer;
@@ -1807,6 +1626,7 @@ begin
for I := 0 to ExceptFrameCount - 1 do
Result := Result + LineEnding + BackTraceStrFunc(Frames[I]);
end;
+{$ENDIF}
initialization
LEOL:=Length(LineEnding);
diff --git a/avx512-0037785/utils/fpdoc/dw_basehtml.pp b/avx512-0037785/utils/fpdoc/dw_basehtml.pp
index c0a82aae25..6dc246a4e9 100644
--- a/avx512-0037785/utils/fpdoc/dw_basehtml.pp
+++ b/avx512-0037785/utils/fpdoc/dw_basehtml.pp
@@ -158,7 +158,7 @@ Function FixHTMLpath(S : String) : STring;
implementation
-uses xmlread, sysutils, sh_pas;
+uses fpdocstrs, xmlread, sysutils, sh_pas;
Function FixHTMLpath(S : String) : STring;
@@ -428,6 +428,7 @@ begin
else
N:='?';
DoLog(SErrUnknownLinkID, [s,n,a]);
+ LinkUnresolvedInc();
PushOutputNode(CreateEl(CurOutputNode, 'b'));
end else
PushOutputNode(CreateLink(CurOutputNode, s));
@@ -797,7 +798,10 @@ begin
TREl:=CreateTR(TableEl);
ParaEl:=CreatePara(CreateTD_vtop(TREl));
l:=El['id'];
- s:= ResolveLinkID(UTF8ENcode(l));
+ if Assigned(Engine) and Engine.FalbackSeeAlsoLinks then
+ s:= ResolveLinkIDUnStrict(UTF8ENcode(l))
+ else
+ s:= ResolveLinkID(UTF8ENcode(l));
if Length(s)=0 then
begin
if assigned(module) then
@@ -806,10 +810,11 @@ begin
s:='?';
if l='' then l:='<empty>';
if Assigned(AElement) then
- N:=UTF8Decode(AElement.Name)
+ N:=UTF8Decode(AElement.PathName)
else
N:='?';
DoLog(SErrUnknownLinkID, [s,N,l]);
+ LinkUnresolvedInc();
NewEl := CreateEl(ParaEl,'b')
end
else
@@ -1007,7 +1012,7 @@ begin
break;
ThisPackage := ThisPackage.NextSibling;
end;
- if Length(s) = 0 then
+ if (Length(s) = 0) and Assigned(Module) then
begin
{ Okay, then we have to try all imported units of the current module }
UnitList := Module.InterfaceSection.UsesList;
@@ -1033,6 +1038,8 @@ begin
end
else if Element is TPasEnumValue then
s := ResolveLinkID(Element.Parent.PathName)
+ else if Element is TPasAliasType then
+ s := ResolveLinkID(TPasAliasType(Element).DestType.PathName)
else
s := ResolveLinkID(Element.PathName);
@@ -1044,7 +1051,10 @@ begin
else
begin
Result := nil;
- AppendText(Parent, Element.Name); // unresolved items
+ if Element is TPasAliasType then
+ AppendText(Parent, TPasAliasType(Element).DestType.Name)
+ else
+ AppendText(Parent, Element.Name); // unresolved items
end;
end;
diff --git a/avx512-0037785/utils/fpdoc/dw_basemd.pp b/avx512-0037785/utils/fpdoc/dw_basemd.pp
index 6ab3e04c39..28e323dfae 100644
--- a/avx512-0037785/utils/fpdoc/dw_basemd.pp
+++ b/avx512-0037785/utils/fpdoc/dw_basemd.pp
@@ -184,15 +184,8 @@ Type
implementation
-resourcestring
- SErrCannotChangeIndentSizeWhenIndented = 'Cannot change indent size while text is indented.';
- SErrIndentMismatch = 'Indent mismatch: trying to undent when current indent too small';
- SErrNotInList = 'Not in list';
- SErrPopListStack = 'Pop list stack list type mismatch';
- SErrMinListStack = 'Min list stack reached';
- SErrMaxListStack = 'Max list stack reached';
- SErrMinIndentStack = 'Min indent stack reached';
- SErrMaxIndentStack = 'Max indent stack reached';
+uses fpdocstrs;
+
procedure TBaseMarkdownWriter.SetIndentSize(AValue: Byte);
begin
@@ -558,6 +551,7 @@ begin
else
N:='?';
DoLog(SErrUnknownLinkID, [s,n,a]);
+ LinkUnresolvedInc();
end
end;
diff --git a/avx512-0037785/utils/fpdoc/dw_chm.pp b/avx512-0037785/utils/fpdoc/dw_chm.pp
index 30195d5b07..31fb05edd8 100644
--- a/avx512-0037785/utils/fpdoc/dw_chm.pp
+++ b/avx512-0037785/utils/fpdoc/dw_chm.pp
@@ -1,5 +1,8 @@
unit dw_chm;
+{$mode objfpc}
+{$h+}
+
interface
uses Classes, DOM,
@@ -40,7 +43,7 @@ type
FAutoIndex: Boolean;
FOtherFiles: String;
procedure ProcessOptions;
- function ResolveLinkIDAbs(const Name: String; Level : Integer = 0): DOMString;
+ function ResolveLinkIDAbs(const Name: String): DOMString;
function RetrieveOtherFiles(const DataName: String; out PathInChm: String;
out FileName: String; var Stream: TStream): Boolean;
procedure LastFileAdded(Sender: TObject);
@@ -50,10 +53,10 @@ type
APasEl: TPasElement; Prefix:String);
procedure GenerateTOC;
procedure GenerateIndex;
+ protected
+ procedure DoWriteDocumentation; override;
public
- procedure WriteDoc; override;
function CreateAllocator: TFileAllocator; override;
-
function InterPretOption(const Cmd,Arg : String): boolean; override;
class procedure Usage(List: TStrings); override;
@@ -63,7 +66,7 @@ type
implementation
-uses SysUtils, HTMWrite, dw_basehtml;
+uses fpdocstrs, SysUtils, HTMWrite, dw_basehtml;
{ TCHmFileNameAllocator }
@@ -72,6 +75,7 @@ var
n,s: String;
i: Integer;
excl: Boolean; //search
+ MElement: TPasElement;
begin
Result:='';
excl := False;
@@ -120,7 +124,9 @@ begin
excl := (ASubindex > 0);
end;
// cut off Package Name
- AElement:= AElement.GetModule;
+ MElement:= AElement.GetModule;
+ if Assigned(MElement) then
+ AElement:= MElement;
Result := Copy(Result, Length(AElement.Parent.Name) + 2, MaxInt);
// to skip dots in unit name
i := Length(AElement.Name);
@@ -163,7 +169,7 @@ end;
{ TCHMHTMLWriter }
-function TCHMHTMLWriter.ResolveLinkIDAbs(const Name: String; Level : Integer = 0): DOMString;
+function TCHMHTMLWriter.ResolveLinkIDAbs(const Name: String): DOMString;
begin
Result:=UTF8Decode(FixHTMLpath(Engine.ResolveLink(Module,Name, True)));
@@ -341,8 +347,10 @@ begin
Continue;
ObjUnitItem := ObjByUnitItem.Children.NewItem;
ObjUnitItem.Text := AModule.Name;
+ ObjUnitItem.addLocal(FixHTMLpath(Allocator.GetFilename(AModule, ClassesSubindex)));
RoutinesUnitItem := RoutinesByUnitItem.Children.NewItem;
RoutinesUnitItem.Text := AModule.Name;
+ RoutinesUnitItem.addLocal(FixHTMLpath(Allocator.GetFilename(AModule, ProcsSubindex)));
for j := 0 to AModule.InterfaceSection.Classes.Count-1 do
begin
Element := TPasClassType(AModule.InterfaceSection.Classes[j]);
@@ -621,7 +629,7 @@ begin
DoLog('Generating Index Done');
end;
-procedure TCHMHTMLWriter.WriteDoc;
+procedure TCHMHTMLWriter.DoWriteDocumentation;
var
i: Integer;
PageDoc: TXMLDocument;
@@ -629,8 +637,6 @@ var
IFileName,FileName: String;
FilePath: String;
begin
- FAllocator:=CreateAllocator;
- FAllocator.SubPageNames:= SubPageNames;
AllocatePages;
DoLog(SWritingPages, [PageCount]);
diff --git a/avx512-0037785/utils/fpdoc/dw_dxml.pp b/avx512-0037785/utils/fpdoc/dw_dxml.pp
index 330faa986a..9f3ef98692 100644
--- a/avx512-0037785/utils/fpdoc/dw_dxml.pp
+++ b/avx512-0037785/utils/fpdoc/dw_dxml.pp
@@ -12,7 +12,7 @@ type
{ TXMLWriter }
TDXMLWriter = class(TFPDocWriter)
- procedure WriteDoc; override;
+ procedure DoWriteDocumentation; override;
end;
{ TDocumentation }
@@ -472,7 +472,7 @@ end;
{ TXMLWriter }
-procedure TDXMLWriter.WriteDoc;
+procedure TDXMLWriter.DoWriteDocumentation;
var
i: integer;
begin
diff --git a/avx512-0037785/utils/fpdoc/dw_html.pp b/avx512-0037785/utils/fpdoc/dw_html.pp
index 298114f9f7..b8afe2be7d 100644
--- a/avx512-0037785/utils/fpdoc/dw_html.pp
+++ b/avx512-0037785/utils/fpdoc/dw_html.pp
@@ -67,7 +67,6 @@ type
procedure FinishElementPage(AElement: TPasElement);virtual;
procedure AppendFooter;virtual;
-
procedure AppendClassMemberListLink(aClass: TPasClassType; ParaEl: TDomElement; AListSubpageIndex: Integer; const AText: DOMString);virtual;
procedure CreateClassMainPage(aClass: TPasClassType);virtual;
procedure CreateClassInheritanceSubpage(aClass: TPasClassType; AFilter: TMemberFilter);virtual;
@@ -97,6 +96,9 @@ type
procedure CreateProcPageBody(AProc: TPasProcedureBase);
Procedure CreateTopicLinks(Node : TDocNode; PasElement : TPasElement);
procedure AppendTypeDecl(AType: TPasType; TableEl, CodeEl: TDomElement);
+ // Main documentation process
+ Procedure DoWriteDocumentation; override;
+
Property HeaderHTML : TStringStream Read FHeaderHTML;
Property NavigatorHTML : TStringStream read FNavigatorHTML;
Property FooterHTML : TStringStream read FFooterHTML;
@@ -104,7 +106,7 @@ type
Property HeadElement : TDomElement Read FHeadElement;
Property TitleElement: TDOMElement Read FTitleElement;
public
- // Creating all module hierarchy classes is here !!!!
+ // Creating all module hierarchy classes happens here !
constructor Create(APackage: TPasPackage; AEngine: TFPDocEngine); override;
// Overrides
Class Function FileNameExtension : String; override;
@@ -112,7 +114,6 @@ type
Class procedure SplitImport(var AFilename, ALinkPrefix: String); override;
Function InterPretOption(Const Cmd,Arg : String) : boolean; override;
- Procedure WriteDoc; override;
// Single-page generation
function CreateHTMLPage(AElement: TPasElement; ASubpageIndex: Integer): TXMLDocument; virtual;
@@ -129,7 +130,7 @@ type
implementation
-uses SysUtils, HTMWrite, fpdocclasstree;
+uses fpdocstrs, SysUtils, HTMWrite, fpdocclasstree;
{$i css.inc}
{$i plusimage.inc}
@@ -207,7 +208,8 @@ begin
PageDoc.Free;
end;
-procedure THTMLWriter.WriteDoc;
+procedure THTMLWriter.DoWriteDocumentation;
+
begin
Inherited;
@@ -338,6 +340,8 @@ function THTMLWriter.AppendProcType(CodeEl, TableEl: TDOMElement;
var
i: Integer;
Arg: TPasArgument;
+ S : String;
+
begin
if Element.Args.Count > 0 then
begin
@@ -347,12 +351,9 @@ begin
begin
Arg := TPasArgument(Element.Args[i]);
CodeEl := CreateIndentedCodeEl(Indent + 2);
-
- case Arg.Access of
- argConst: AppendKw(CodeEl, 'const ');
- argVar: AppendKw(CodeEl, 'var ');
- argOut: AppendKw(CodeEl, 'out ');
- end;
+ S:=AccessNames[Arg.Access];
+ if (S<>'') then
+ AppendKw(CodeEl,S);
AppendText(CodeEl, Arg.Name);
if Assigned(Arg.ArgType) then
begin
@@ -1743,7 +1744,6 @@ end;
procedure THTMLWriter.CreateClassMainPage(aClass : TPasClassType);
procedure AppendGenericTypes(CodeEl : TDomElement; AList : TFPList; isSpecialize : Boolean);
-
Var
I : integer;
begin
@@ -1758,12 +1758,35 @@ procedure THTMLWriter.CreateClassMainPage(aClass : TPasClassType);
AppendSym(CodeEl, '>');
end;
+ procedure AppendGeneric(ACodeEl : TDomElement ; AGenericObject: TPasClassType);
+ begin
+ if AGenericObject.GenericTemplateTypes.Count>0 then
+ begin
+ AppendKw(ACodeEl, ' generic ');
+ AppendText(ACodeEl, ' ' + UTF8Decode(AGenericObject.Name) + ' ');
+ AppendGenericTypes(ACodeEl,AGenericObject.GenericTemplateTypes,false);
+ end;
+ end;
+
+ procedure AppendInterfaceInfo(ACodeEl : TDomElement ; AThisClass: TPasClassType);
+ var
+ i:Integer;
+ ThisInterface:TPasClassType;
+ begin
+ if Assigned(AThisClass) and (AThisClass.Interfaces.count>0) then
+ begin
+ for i:=0 to AThisClass.interfaces.count-1 do
+ begin
+ ThisInterface:=TPasClassType(AThisClass.Interfaces[i]);
+ AppendText(ACodeEl,',');
+ AppendHyperlink(ACodeEl, ThisInterface);
+ end;
+ end;
+ end;
var
ParaEl,TableEl, TREl, TDEl, CodeEl: TDOMElement;
- i: Integer;
- ThisInterface,
- ThisClass: TPasClassType;
+ ThisClass, PrevClass: TPasType;
ThisTreeNode: TPasElementNode;
begin
//WriteLn('@ClassPageBody.CreateMainPage Class=', AClass.Name);
@@ -1785,41 +1808,55 @@ begin
TDEl := CreateTD(TREl);
CodeEl := CreateCode(CreatePara(TDEl));
AppendKw(CodeEl, 'type');
+
+ if not Assigned(AClass.GenericTemplateTypes) then
+ Dolog('ERROR generic init: %s', [AClass.name]);
if AClass.GenericTemplateTypes.Count>0 then
- AppendKw(CodeEl, ' generic ');
- AppendText(CodeEl, ' ' + UTF8Decode(AClass.Name) + ' ');
- if AClass.GenericTemplateTypes.Count>0 then
- AppendGenericTypes(CodeEl,AClass.GenericTemplateTypes,false);
+ AppendGeneric(CodeEl, AClass)
+ else
+ AppendText(CodeEl, ' ' + UTF8Decode(AClass.Name) + ' ');
+
AppendSym(CodeEl, '=');
AppendText(CodeEl, ' ');
AppendKw(CodeEl, UTF8Decode(ObjKindNames[AClass.ObjKind]));
+ // Now we are using only TreeClass for show inheritance
+
+ ThisClass := AClass; ThisTreeNode := Nil;
+ if AClass.ObjKind = okInterface then
+ ThisTreeNode := TreeInterface.GetPasElNode(AClass)
+ else
+ ThisTreeNode := TreeClass.GetPasElNode(AClass);
+ if not Assigned(ThisTreeNode) Then
+ DoLog('ERROR Tree Class information: '+ThisClass.PathName);
+
if Assigned(AClass.AncestorType) then
begin
AppendSym(CodeEl, '(');
- AppendHyperlink(CodeEl, AClass.AncestorType);
- if AClass.Interfaces.count>0 Then
- begin
- for i:=0 to AClass.interfaces.count-1 do
- begin
- AppendSym(CodeEl, ', ');
- AppendHyperlink(CodeEl,TPasClassType(AClass.Interfaces[i]));
- end;
- end;
+ // Show parent class information
+ if (AClass.AncestorType is TPasSpecializeType) then
+ begin
+ AppendText(CodeEl, 'specialize ');
+ AppendHyperlink(CodeEl, TPasSpecializeType(AClass.AncestorType).DestType);
+ AppendText(CodeEl, '<,>');
+ end
+ else
+ begin
+ AppendHyperlink(CodeEl, AClass.AncestorType);
+ AppendInterfaceInfo(CodeEl, AClass);
+ end;
AppendSym(CodeEl, ')');
end;
+ // Class members
CreateMemberDeclarations(AClass, AClass.Members,TableEl, not AClass.IsShortDefinition);
AppendText(CreateH2(ContentElement), UTF8Decode(SDocInheritance));
TableEl := CreateTable(ContentElement);
- // Now we are using only TreeClass for show inheritance
+ // Process tree class information
+ // First tree class link is to This class
+ PrevClass:= nil;
- ThisClass := AClass; ThisTreeNode := Nil;
- if AClass.ObjKind = okInterface then
- ThisTreeNode := TreeInterface.GetPasElNode(AClass)
- else
- ThisTreeNode := TreeClass.GetPasElNode(AClass);
while True do
begin
TREl := CreateTR(TableEl);
@@ -1828,23 +1865,10 @@ begin
CodeEl := CreateCode(CreatePara(TDEl));
// Show class item
- if Assigned(ThisClass) Then
- AppendHyperlink(CodeEl, ThisClass);
- //else
- // AppendHyperlink(CodeEl, ThisTreeNode);
- // Show links to class interfaces
- if Assigned(ThisClass) and (ThisClass.Interfaces.count>0) then
- begin
- for i:=0 to ThisClass.interfaces.count-1 do
- begin
- ThisInterface:=TPasClassType(ThisClass.Interfaces[i]);
- AppendText(CodeEl,',');
- AppendHyperlink(CodeEl, ThisInterface);
- end;
- end;
- // short class description
- if Assigned(ThisClass) then
- AppendShortDescrCell(TREl, ThisClass);
+ AppendHyperlink(CodeEl, ThisClass);
+ if Assigned(PrevClass) and (PrevClass Is TPasClassType) then // Interfaces from prevClass
+ AppendInterfaceInfo(CodeEl, TPasClassType(PrevClass));
+ AppendShortDescrCell(TREl, ThisClass);
if Assigned(ThisTreeNode) then
if Assigned(ThisTreeNode.ParentNode) then
@@ -1852,6 +1876,7 @@ begin
TDEl := CreateTD(CreateTR(TableEl));
TDEl['align'] := 'center';
AppendText(TDEl, '|');
+ PrevClass:= ThisClass;
ThisClass := ThisTreeNode.ParentNode.Element;
ThisTreeNode := ThisTreeNode.ParentNode;
end
@@ -1859,6 +1884,7 @@ begin
begin
ThisClass := nil;
ThisTreeNode:= nil;
+ PrevClass:= nil;
break;
end
else
diff --git a/avx512-0037785/utils/fpdoc/dw_ipflin.pas b/avx512-0037785/utils/fpdoc/dw_ipflin.pas
index 8bf9e117cc..b8bdf9c981 100644
--- a/avx512-0037785/utils/fpdoc/dw_ipflin.pas
+++ b/avx512-0037785/utils/fpdoc/dw_ipflin.pas
@@ -151,7 +151,7 @@ type
implementation
uses
- SysUtils, dwriter;
+ fpdocstrs, SysUtils, dwriter;
{ TFPDocWriter overrides }
diff --git a/avx512-0037785/utils/fpdoc/dw_latex.pp b/avx512-0037785/utils/fpdoc/dw_latex.pp
index ce04c3a082..d353bf1011 100644
--- a/avx512-0037785/utils/fpdoc/dw_latex.pp
+++ b/avx512-0037785/utils/fpdoc/dw_latex.pp
@@ -30,7 +30,7 @@ Procedure CreateLaTeXDocForPackage(APackage: TPasPackage; AEngine: TFPDocEngine)
implementation
-uses SysUtils, Classes, dwLinear, dwriter;
+uses fpdocstrs, SysUtils, Classes, dwLinear, dwriter;
Type
@@ -638,7 +638,7 @@ var
begin
Writer := TLaTeXWriter.Create(APackage, AEngine);
try
- Writer.WriteDoc;
+ Writer.DoWriteDocumentation;
finally
Writer.Free;
end;
diff --git a/avx512-0037785/utils/fpdoc/dw_linrtf.pp b/avx512-0037785/utils/fpdoc/dw_linrtf.pp
index dd25f5a7f0..35a8667b27 100644
--- a/avx512-0037785/utils/fpdoc/dw_linrtf.pp
+++ b/avx512-0037785/utils/fpdoc/dw_linrtf.pp
@@ -28,7 +28,7 @@ Procedure CreateRTFDocForPackage(APackage: TPasPackage; AEngine: TFPDocEngine);
implementation
-uses SysUtils, Classes, dwLinear, dwriter;
+uses fpdocstrs, SysUtils, Classes, dwLinear, dwriter;
const
Indent = 300;
@@ -782,7 +782,7 @@ var
begin
Writer := TRTFWriter.Create(APackage, AEngine);
try
- Writer.WriteDoc;
+ Writer.DoWriteDocumentation;
finally
Writer.Free;
end;
diff --git a/avx512-0037785/utils/fpdoc/dw_man.pp b/avx512-0037785/utils/fpdoc/dw_man.pp
index 1874bdf1ef..6811d5c858 100644
--- a/avx512-0037785/utils/fpdoc/dw_man.pp
+++ b/avx512-0037785/utils/fpdoc/dw_man.pp
@@ -99,9 +99,10 @@ Type
Procedure WriteExampleFile(FN : String); virtual;
procedure WriteExample(ADocNode: TDocNode);
procedure WriteSeeAlso(ADocNode: TDocNode; Comma : Boolean);
+ // Here we write the documentation.
+ procedure DoWriteDocumentation; override;
Public
Constructor Create(APackage: TPasPackage; AEngine: TFPDocEngine); override;
- procedure WriteDoc; override;
// Documentation writing methods.
// Package
Procedure WritePackagePage;
@@ -185,6 +186,8 @@ Type
implementation
+uses fpdocstrs;
+
{ TManWriter }
constructor TManWriter.Create(APackage: TPasPackage; AEngine: TFPDocEngine);
@@ -968,7 +971,7 @@ end;
Actual man page writing
---------------------------------------------------------------------}
-procedure TManWriter.WriteDoc;
+procedure TManWriter.DoWriteDocumentation;
var
i : Integer;
diff --git a/avx512-0037785/utils/fpdoc/dw_markdown.pp b/avx512-0037785/utils/fpdoc/dw_markdown.pp
index e9a74d90b6..15358fa9e9 100644
--- a/avx512-0037785/utils/fpdoc/dw_markdown.pp
+++ b/avx512-0037785/utils/fpdoc/dw_markdown.pp
@@ -116,6 +116,8 @@ type
procedure CreateClassMemberPageBody(AElement: TPasElement); virtual;
procedure CreateInheritanceSubpage(aClass: TPasClassType; aTitle : string; AFilter: TMemberFilter); virtual;
procedure CreateSortedSubpage(ACLass: TPasClassType; aTitle : string; AFilter: TMemberFilter ); virtual;
+ // Here we write the documentation
+ Procedure DoWriteDocumentation; override;
public
constructor Create(APackage: TPasPackage; AEngine: TFPDocEngine); override;
destructor Destroy; override;
@@ -126,7 +128,6 @@ type
// Start producing html complete package documentation
Function InterPretOption(Const Cmd,Arg : String) : boolean; override;
- Procedure WriteDoc; override;
Class Function FileNameExtension : String; override;
class procedure Usage(List: TStrings); override;
Class procedure SplitImport(var AFilename, ALinkPrefix: String); override;
@@ -142,7 +143,7 @@ type
implementation
-uses SysUtils, fpdocclasstree;
+uses fpdocstrs, SysUtils, fpdocclasstree;
Function FixHTMLpath(S : String) : STring;
@@ -300,9 +301,7 @@ begin
end;
end;
-
-
-procedure TMarkdownWriter.WriteDoc;
+procedure TMarkdownWriter.DoWriteDocumentation;
begin
Inherited;
@@ -310,7 +309,6 @@ begin
WriteMkdocsYaml;
end;
-
function TMarkdownWriter.GetFooterMarkDown: TStrings;
begin
If FFooterMarkDown=Nil then
@@ -423,7 +421,7 @@ begin
break;
ThisPackage := ThisPackage.NextSibling;
end;
- if Length(s) = 0 then
+ if (Length(s) = 0) and Assigned(Module) then
begin
{ Okay, then we have to try all imported units of the current module }
UnitList := Module.InterfaceSection.UsesList;
@@ -650,6 +648,7 @@ procedure TMarkdownWriter.AppendSeeAlsoSection(AElement: TPasElement; DocNode: T
else
N:='?';
DoLog(SErrUnknownLinkID, [s,N,aID]);
+ LinkUnresolvedInc();
end ;
if doBold then
DescrBeginBold
@@ -1474,12 +1473,19 @@ begin
if aEL.ExternalName<>'' then
aLine:=aLine+' external name '''+ael.ExternalName+'''';
if Assigned(aEL.AncestorType) then
+ if (aEL.AncestorType is TPasSpecializeType) then
begin
- aLine:=aLine+' ('+ael.AncestorType.Name;
- if Assigned(ael.Interfaces) and (aEl.Interfaces.Count>0) then
- For I:=0 to aEl.Interfaces.Count-1 do
- aLine:=aLine+', '+TPasElement(aEl.Interfaces[i]).Name;
- aLine:=aLine+')';
+ aLine:=aLine+'(specialize ';
+ aLine:=aLine+ TPasSpecializeType(aEL.AncestorType).DestType.Name;
+ aLine:=aLine+ '<,>)';
+ end
+ else
+ begin
+ aLine:=aLine+' ('+ael.AncestorType.Name;
+ if Assigned(ael.Interfaces) and (aEl.Interfaces.Count>0) then
+ For I:=0 to aEl.Interfaces.Count-1 do
+ aLine:=aLine+', '+TPasElement(aEl.Interfaces[i]).Name;
+ aLine:=aLine+')';
end;
if Assigned(aEl.GUIDExpr) then
aLine:=aLine+' ['+aEl.GUIDExpr.GetDeclaration(True)+']';
@@ -1578,7 +1584,7 @@ procedure TMarkdownWriter.CreateClassMainPage(aClass : TPasClassType);
var
i: Integer;
ThisInterface,
- ThisClass: TPasClassType;
+ ThisClass: TPasType;
ThisTreeNode: TPasElementNode;
DocNode: TDocNode;
@@ -1628,12 +1634,12 @@ begin
// Show class item
if Assigned(ThisClass) Then
AppendHyperlink(ThisClass);
- if Assigned(ThisClass) and (ThisClass.Interfaces.count>0) then
+ if Assigned(ThisClass) and (AClass.Interfaces.count>0) then
begin
AppendText('(');
- for i:=0 to ThisClass.interfaces.count-1 do
+ for i:=0 to AClass.interfaces.count-1 do
begin
- ThisInterface:=TPasClassType(ThisClass.Interfaces[i]);
+ ThisInterface:= TPasType(AClass.Interfaces[i]);
if I>0 then
AppendText(', ');
AppendHyperlink( ThisInterface);
diff --git a/avx512-0037785/utils/fpdoc/dw_txt.pp b/avx512-0037785/utils/fpdoc/dw_txt.pp
index 9557b196d2..3305f2eb88 100644
--- a/avx512-0037785/utils/fpdoc/dw_txt.pp
+++ b/avx512-0037785/utils/fpdoc/dw_txt.pp
@@ -28,7 +28,7 @@ Procedure CreateTxtDocForPackage(APackage: TPasPackage; AEngine: TFPDocEngine);
implementation
-uses SysUtils, Classes, dwLinear;
+uses fpdocstrs, SysUtils, Classes, dwLinear;
Const
MaxListLevel = 10;
@@ -603,7 +603,7 @@ var
begin
Writer := TTxtWriter.Create(APackage, AEngine);
try
- Writer.WriteDoc;
+ Writer.DoWriteDocumentation;
finally
Writer.Free;
end;
diff --git a/avx512-0037785/utils/fpdoc/dw_xml.pp b/avx512-0037785/utils/fpdoc/dw_xml.pp
index 1f7bfbce51..b1ccbdcdc6 100644
--- a/avx512-0037785/utils/fpdoc/dw_xml.pp
+++ b/avx512-0037785/utils/fpdoc/dw_xml.pp
@@ -38,10 +38,11 @@ Type
procedure AllocatePackagePages; override;
procedure AllocateModulePages(AModule: TPasModule; {%H-}LinkList: TObjectList); override;
procedure WriteDocPage(const aFileName: String; aElement: TPasElement; {%H-}aSubPageIndex: Integer); override;
+ // Here we write the documentation.
+ Procedure DoWriteDocumentation; override;
public
constructor Create(APackage: TPasPackage; AEngine: TFPDocEngine); override;
function ModuleToXMLStruct(AModule: TPasModule): TXMLDocument;
- Procedure WriteDoc; override;
class procedure Usage(List: TStrings); override;
function InterPretOption(const Cmd,Arg : String): boolean; override;
end;
@@ -61,6 +62,8 @@ Type
implementation
+uses fpdocstrs;
+
const
DefaultVisibility = [visDefault, visPublic, visPublished, visProtected];
@@ -108,6 +111,8 @@ var
visAutomated : Result := 'automated';
visStrictPrivate : Result := 'strictprivate';
visStrictProtected : Result := 'strictprotected';
+ visRequired : Result := 'required';
+ visOptional : Result := 'optional';
end;
end;
@@ -629,9 +634,9 @@ end;
{ TXMLWriter }
-procedure TXMLWriter.WriteDoc;
+procedure TXMLWriter.DoWriteDocumentation;
begin
- inherited WriteDoc;
+ inherited DoWriteDocumentation;
end;
function TXMLWriter.CreateAllocator: TFileAllocator;
diff --git a/avx512-0037785/utils/fpdoc/dwlinear.pp b/avx512-0037785/utils/fpdoc/dwlinear.pp
index 5b36cec805..c19c1f3a26 100644
--- a/avx512-0037785/utils/fpdoc/dwlinear.pp
+++ b/avx512-0037785/utils/fpdoc/dwlinear.pp
@@ -89,11 +89,12 @@ Type
Property LastURL : DomString Read FLastURL Write FLastURL;
// Overriden from fpdocwriter;
procedure DescrWriteText(const AText: DOMString); override;
+ // Actual writing happens here.
+ Procedure DoWriteDocumentation; override;
Public
Constructor Create(APackage: TPasPackage; AEngine: TFPDocEngine); override;
function InterpretOption(const Cmd, Arg: String): Boolean; override;
class procedure Usage(List: TStrings); override;
- procedure WriteDoc; override;
// Linear Documentation writing methods.
Procedure ProcessPackage;
Procedure ProcessTopics(DocNode : TDocNode; Alevel : Integer);
@@ -121,6 +122,8 @@ Type
implementation
+uses fpdocstrs;
+
const
cDupLinkedDocParam = '--duplinkeddoc';
@@ -591,7 +594,7 @@ begin
Result := '<nil>';
end;
-procedure TLinearWriter.WriteDoc;
+procedure TLinearWriter.DoWriteDocumentation;
var
i : Integer;
diff --git a/avx512-0037785/utils/fpdoc/dwriter.pp b/avx512-0037785/utils/fpdoc/dwriter.pp
index eb0bf599cf..e22d1d7ba4 100644
--- a/avx512-0037785/utils/fpdoc/dwriter.pp
+++ b/avx512-0037785/utils/fpdoc/dwriter.pp
@@ -27,31 +27,6 @@ interface
uses Classes, DOM, contnrs, dGlobals, PasTree, SysUtils, fpdocclasstree;
-resourcestring
- SErrFileWriting = 'An error occurred during writing of file "%s": %s';
-
- SErrInvalidShortDescr = 'Invalid short description';
- SErrInvalidDescr = 'Invalid description (illegal XML element: "%s")';
- SErrInvalidParaContent = 'Invalid paragraph content';
- SErrInvalidElementInList = 'Invalid element in list - only "li" allowed';
- SErrInvalidListContent = 'Invalid list content';
- SErrInvalidRemarkContent = 'Invalid <remark> content (illegal XML element: "%s")';
- SErrListIsEmpty = 'List is empty - need at least one "li" element';
- SErrInvalidDefinitionTermContent = 'Invalid content in definition term';
- SErrDefinitionEntryMissing = 'Definition entry after definition term is missing';
- SErrInvalidBorderValue = 'Invalid "border" value for %s';
- SErrInvalidTableContent = 'Invalid table content';
- SErrTableRowEmpty = 'Table row is empty (no "td" elements found)';
- SErrInvalidContentBeforeSectionTitle = 'Invalid content before section title';
- SErrSectionTitleExpected = 'Section title ("title" element) expected';
-
- SErrDescrTagUnknown = 'Warning: Unknown tag "%s" in description';
- SErrUnknownEntityReference = 'Warning: Unknown entity reference "&%s;" found';
- SErrUnknownLinkID = 'Warning: Target ID of <link> in unit "%s", element "%s", is unknown: "%s"';
- SErrUnknownPrintShortID = 'Warning: Target ID of <printshort> is unknown: "%s"';
- SErrUnknownLink = 'Could not resolve link to "%s"';
- SErralreadyRegistered = 'Class for output format "%s" already registered';
- SErrUnknownWriterClass = 'Unknown output format "%s"';
type
// Phony element for pas pages.
@@ -116,6 +91,7 @@ type
procedure AddElementsFromList(L: TStrings; List: TFPList; UsePathName : Boolean = False);
Procedure DoLog(Const Msg : String);
Procedure DoLog(Const Fmt : String; Args : Array of const);
+ Procedure OutputResults(); virtual;
procedure Warning(AContext: TPasElement; const AMsg: String);
procedure Warning(AContext: TPasElement; const AMsg: String;
const Args: array of const);
@@ -194,6 +170,9 @@ type
procedure DescrEndTableRow; virtual; abstract;
procedure DescrBeginTableCell; virtual; abstract;
procedure DescrEndTableCell; virtual; abstract;
+ procedure PrepareDocumentation; virtual;
+ // Descendents must override this.
+ procedure DoWriteDocumentation; virtual; Abstract;
Property CurrentContext : TPasElement Read FContext ;
public
@@ -209,7 +188,8 @@ type
Class Function FileNameExtension : String; virtual;
Class Procedure Usage(List : TStrings); virtual;
Class procedure SplitImport(var AFilename, ALinkPrefix: String); virtual;
- procedure WriteDoc; virtual; Abstract;
+ // Here we start the generation of documentation
+ procedure WriteDocumentation;
Function WriteDescr(Element: TPasElement) : TDocNode;
procedure WriteDescr(Element: TPasElement; DocNode: TDocNode);
procedure WriteDescr(AContext: TPasElement; DescrNode: TDOMElement); virtual;
@@ -275,14 +255,23 @@ Type
FCurDirectory: String;
FModule: TPasModule;
FPageInfos: TFPObjectList; // list of TPageInfo objects
+ FLinkUnresolvedCnt: Integer;
+ FOutputPageNames: TStringList;
+ function GetOutputPageNames: TStrings;
function GetPageCount: Integer;
-
+ function LinkFix(ALink:String):String;
Protected
FAllocator: TFileAllocator;
- function ResolveLinkID(const Name: String; Level: Integer=0): DOMString;
+ Procedure LinkUnresolvedInc();
+ // General resolving routine
+ function ResolveLinkID(const Name: String): DOMString;
+ // Simplified resolving routine. Excluded last path after dot
+ function ResolveLinkIDUnStrict(const Name: String): DOMString;
function ResolveLinkIDInUnit(const Name,AUnitName: String): DOMString;
function ResolveLinkWithinPackage(AElement: TPasElement; ASubpageIndex: Integer): String;
- Function CreateAllocator : TFileAllocator; virtual; abstract;
+ procedure PrepareDocumentation; override;
+ function CreateAllocator() : TFileAllocator; virtual; abstract;
+ Procedure OutputResults(); override;
// aFileName is the filename allocated by the Allocator, nothing prefixed.
procedure WriteDocPage(const aFileName: String; aElement: TPasElement; aSubPageIndex: Integer); virtual; abstract;
procedure AllocatePages; virtual;
@@ -297,18 +286,22 @@ Type
function GetFileBaseDir(aOutput: String): String; virtual;
function InterPretOption(const Cmd, Arg: String): boolean; override;
function ModuleHasClasses(AModule: TPasModule): Boolean;
+ // Allocate pages etc.
+ Procedure DoWriteDocumentation; override;
+ Function MustGeneratePage(aFileName : String) : Boolean; virtual;
+
Property PageInfos : TFPObjectList Read FPageInfos;
Property SubPageNames: Boolean Read FSubPageNames;
Public
constructor Create(APackage: TPasPackage; AEngine: TFPDocEngine); override;
Destructor Destroy; override;
- procedure WriteDoc; override;
class procedure Usage(List: TStrings); override;
property PageCount: Integer read GetPageCount;
Property Allocator : TFileAllocator Read FAllocator;
Property Module: TPasModule Read FModule Write FModule;
Property CurDirectory: String Read FCurDirectory Write FCurDirectory; // relative to curdir of process
property BaseDirectory: String read FBaseDirectory Write FBaseDirectory; // relative path to package base directory
+ Property OutputPageNames : TStrings Read GetOutputPageNames;
end;
TFPDocWriterClass = Class of TFPDocWriter;
@@ -339,6 +332,8 @@ function SortPasElements(Item1, Item2: Pointer): Integer;
implementation
+uses strutils, fpdocstrs;
+
function SortPasElements(Item1, Item2: Pointer): Integer;
begin
Result:=CompareText(TPasElement(Item1).Name,TPasElement(Item2).Name)
@@ -412,6 +407,7 @@ begin
inherited Create(APackage, AEngine);
FPageInfos:=TFPObjectList.Create;
FSubPageNames:= False;
+ FLinkUnresolvedCnt:=0;
end;
destructor TMultiFileDocWriter.Destroy;
@@ -426,23 +422,80 @@ begin
Result := PageInfos.Count;
end;
-function TMultiFileDocWriter.ResolveLinkID(const Name: String; Level : Integer = 0): DOMString;
+function TMultiFileDocWriter.GetOutputPageNames: TStrings;
+begin
+ If (FoutputPageNames=Nil) then
+ begin
+ FOutputPageNames:=TStringList.Create;
+ FOutputPageNames.Sorted:=True;
+ end;
+ Result:=FOutputPageNames;
+end;
+
+procedure TMultiFileDocWriter.OutputResults();
+begin
+ DoLog('Unresolved links: %d', [FLinkUnresolvedCnt]);
+ inherited OutputResults();
+end;
+
+procedure TMultiFileDocWriter.LinkUnresolvedInc();
+begin
+ Inc(FLinkUnresolvedCnt);
+end;
+function TMultiFileDocWriter.ResolveLinkID(const Name: String): DOMString;
var
- res,s: String;
+ res: String;
begin
res:=Engine.ResolveLink(Module,Name, True);
// engine can return backslashes on Windows
+ res:= LinkFix(res);
+ Result:=UTF8Decode(res);
+end;
+
+function TMultiFileDocWriter.ResolveLinkIDUnStrict(const Name: String
+ ): DOMString;
+var
+ idDot, idLast: Integer;
+ res: String;
+begin
+ res:=Engine.ResolveLink(Module,Name, True);
+ if res = '' then
+ begin
+ // do simplify on one level from end.
+ // TOCO: I want to move that code to last check of Engine.ResolveLink() for not Strict
+ IdDot:= Pos('.', Name);
+ IdLast:= 0;
+ // search last dot
+ while idDot > 0 do
+ begin
+ IdLast:= idDot;
+ IdDot:= Pos('.', Name, IdLast+1);
+ end;
+ if idLast > 0 then
+ // have cut last element
+ res:= Engine.ResolveLink(Module, Copy(Name, 1, IdLast-1), True);
+ end;
+ res:= LinkFix(res);
+ Result:=UTF8Decode(res);
+end;
+
+function TMultiFileDocWriter.LinkFix(ALink: String): String;
+var
+ res, s:String;
+begin
+ res:= ALink;
if Length(res) > 0 then
- begin
- s:=Copy(Res, 1, Length(CurDirectory) + 1);
+ begin
+ // If the link is in the same directory as current dir, then remove the directory part.
+ s:=Copy(res, 1, Length(CurDirectory) + 1);
if (S= CurDirectory + '/') or (s= CurDirectory + '\') then
- Res := Copy(Res, Length(CurDirectory) + 2, Length(Res))
- else if not IsLinkAbsolute(Res) then
- Res := BaseDirectory + Res;
- end;
- Result:=UTF8Decode(Res);
+ res := Copy(res, Length(CurDirectory) + 2, Length(res))
+ else if not IsLinkAbsolute(res) then
+ res := BaseDirectory + res;
+ end;
+ Result:= res;
end;
{ Used for:
@@ -482,8 +535,15 @@ begin
SetLength(Result, 0);
end;
+procedure TMultiFileDocWriter.PrepareDocumentation;
+begin
+ inherited PrepareDocumentation;
+ FAllocator:= CreateAllocator();
+ FAllocator.SubPageNames:= SubPageNames;
+end;
-Function TMultiFileDocWriter.AddPage(AElement: TPasElement; ASubpageIndex: Integer) : TPageInfo;
+function TMultiFileDocWriter.AddPage(AElement: TPasElement;
+ ASubpageIndex: Integer): TPageInfo;
begin
Result:= TPageInfo.Create(aElement,aSubPageIndex);
@@ -531,7 +591,7 @@ begin
end;
-Function TMultiFileDocWriter.ModuleHasClasses(AModule: TPasModule) : Boolean;
+function TMultiFileDocWriter.ModuleHasClasses(AModule: TPasModule): Boolean;
begin
result:=assigned(AModule)
@@ -574,7 +634,8 @@ begin
end;
end;
-Procedure TMultiFileDocWriter.AllocateClassMemberPages(AModule: TPasModule; LinkList : TObjectList);
+procedure TMultiFileDocWriter.AllocateClassMemberPages(AModule: TPasModule;
+ LinkList: TObjectList);
var
i, j, k: Integer;
ClassEl: TPasClassType;
@@ -738,7 +799,7 @@ begin
Result:=IncludeTrailingPathDelimiter(Result);
end;
-procedure TMultiFileDocWriter.WriteDoc;
+procedure TMultiFileDocWriter.DoWriteDocumentation;
procedure CreatePath(const AFilename: String);
@@ -771,8 +832,6 @@ var
FinalFilename: String;
begin
- FAllocator:=CreateAllocator;
- FAllocator.SubPageNames:= SubPageNames;
AllocatePages;
DoLog(SWritingPages, [PageCount]);
if Engine.Output <> '' then
@@ -781,23 +840,60 @@ begin
with TPageInfo(PageInfos[i]) do
begin
FileName:= Allocator.GetFilename(Element, SubpageIndex);
- FinalFilename := GetFileBaseDir(Engine.Output) + FileName;
- CreatePath(FinalFilename);
- WriteDocPage(FileName,ELement,SubPageIndex);
+ if MustGeneratePage(FileName) then
+ begin
+ FinalFilename := GetFileBaseDir(Engine.Output) + FileName;
+ CreatePath(FinalFilename);
+ WriteDocPage(FileName,ELement,SubPageIndex);
+ end;
end;
end;
+function TMultiFileDocWriter.MustGeneratePage(aFileName: String): Boolean;
+begin
+ Result:=Not Assigned(FOutputPageNames);
+ if Not Result then
+ Result:=FOutputPageNames.IndexOf(aFileName)<>-1;
+ Writeln(afilename ,': ',result);
+end;
+
class procedure TMultiFileDocWriter.Usage(List: TStrings);
begin
List.AddStrings(['--use-subpagenames', SUsageSubNames]);
+ List.AddStrings(['--only-pages=LIST', SUsageOnlyPages]);
end;
function TMultiFileDocWriter.InterPretOption(const Cmd, Arg: String): boolean;
+
+Var
+ I : Integer;
+ FN : String;
+
begin
+ Writeln('Cmd : ',Cmd);
Result := True;
if Cmd = '--use-subpagenames' then
FSubPageNames:= True
else
+ if Cmd = '--only-pages' then
+ begin
+ Result:=Arg<>'';
+ if Result then
+ begin
+ if Arg[1]='@' then
+ begin
+ FN:=Copy(Arg,2,Length(Arg)-1);
+ OutputPageNames.LoadFromFile(FN);
+ end
+ else
+ begin
+ For I:=1 to WordCount(Arg,[',']) do
+ OutputPageNames.Add(ExtractWord(I,Arg,[',']));
+ end;
+ Writeln('OutputPagenames ',OutputPagenames.CommaText);
+ end
+ end
+ else
Result:=inherited InterPretOption(Cmd, Arg);
end;
@@ -971,7 +1067,7 @@ function TLongNameFileAllocator.GetFilename(AElement: TPasElement; ASubindex: In
var
n,s: String;
i: Integer;
-
+ MElement: TPasElement;
begin
Result:='';
if AElement.ClassType = TPasPackage then
@@ -1009,7 +1105,9 @@ begin
end else
Result := LowerCase(AElement.PathName);
// cut off Package Name
- AElement:= AElement.GetModule;
+ MElement:= AElement.GetModule;
+ if Assigned(MElement) then
+ AElement:= MElement;
Result := Copy(Result, Length(AElement.Parent.Name) + 2, MaxInt);
// to skip dots in unit name
i := Length(AElement.Name);
@@ -1065,8 +1163,8 @@ begin
FPackage := APackage;
FTopics:=Tlist.Create;
FImgExt:='.png';
- TreeClass:= TClassTreeBuilder.Create(FEngine, FPackage, okClass);
- TreeInterface:= TClassTreeBuilder.Create(FEngine, FPackage, okInterface);
+ TreeClass:= TClassTreeBuilder.Create(FEngine, FPackage, okWithFields);
+ TreeInterface:= TClassTreeBuilder.Create(FEngine, FPackage, [okInterface]);
CreateClassTree;
end;
@@ -1129,6 +1227,13 @@ begin
end;
end;
+procedure TFPDocWriter.WriteDocumentation;
+begin
+ PrepareDocumentation();
+ DoWriteDocumentation();
+ OutputResults();
+end;
+
function TFPDocWriter.FindTopicElement ( Node: TDocNode ) : TTopicElement;
Var
@@ -1152,6 +1257,11 @@ begin
DoLog('%s : No support for images yet: %s (caption: "%s")',[ClassName,AFileName,ACaption]);
end;
+procedure TFPDocWriter.PrepareDocumentation;
+begin
+ // Ancestors can call AllocatePages();CreateAllocator(); into base class
+end;
+
{ ---------------------------------------------------------------------
Generic documentation node conversion
---------------------------------------------------------------------}
@@ -1509,6 +1619,11 @@ begin
DoLog(Format(Fmt,Args));
end;
+procedure TFPDocWriter.OutputResults();
+begin
+ DoLog('Package: %s - Documentation process finished.', [FPackage.Name]);
+end;
+
function TFPDocWriter.ConvertExtShort(AContext: TPasElement;
Node: TDOMNode): Boolean;
begin
@@ -1722,8 +1837,8 @@ begin
if Node.NodeType <> ELEMENT_NODE then
begin
if Node.NodeType = TEXT_NODE then
- Result := IsWhitespaceNode(TDOMText(Node))
- else
+ Result := IsWhitespaceNode(TDOMText(Node))
+ else
Result := Node.NodeType = COMMENT_NODE;
exit;
end;
diff --git a/avx512-0037785/utils/fpdoc/fpclasschart.pp b/avx512-0037785/utils/fpdoc/fpclasschart.pp
index 1ce706f8bb..4172a5d81b 100644
--- a/avx512-0037785/utils/fpdoc/fpclasschart.pp
+++ b/avx512-0037785/utils/fpdoc/fpclasschart.pp
@@ -42,7 +42,7 @@ type
FTree : TClassTreeBuilder;
FObjects : TStringList;
public
- Constructor Create(AClassTree : TXMLDocument; AObjectKind : TPasObjKind);
+ Constructor Create(AClassTree : TXMLDocument; AObjectKindSet : TPasObjKindSet);
Destructor Destroy; override;
function CreateElement(AClass: TPTreeElement; const AName: String;
AParent: TPasElement; AVisibility :TPasMemberVisibility;
@@ -442,14 +442,12 @@ begin
end;
end;
-Constructor TClassTreeEngine.Create(AClassTree : TXMLDocument; AObjectKind : TPasObjKind);
-
-
+Constructor TClassTreeEngine.Create(AClassTree : TXMLDocument; AObjectKindSet : TPasObjKindSet);
begin
+ Inherited Create;
FPackage:=TPasPackage.Create('dummy',Nil);
- FTree:=TClassTreeBuilder.Create(Self,FPackage,AObjectKind);
+ FTree:=TClassTreeBuilder.Create(Self,FPackage,AObjectKindSet);
FObjects:=TStringList.Create;
- Inherited Create;
end;
destructor TClassTreeEngine.Destroy;
@@ -538,11 +536,13 @@ Var
end;
begin
+ Result:= 0;
aSrc:=TXMLDocument.Create();
try
aSrc.AppendChild(aSrc.CreateElement('TObject'));
AppendChildClasses(aSrc.DocumentElement,aRootNode);
MergeTrees(Dest,aSrc);
+ Inc(Result);
finally
aSrc.Free;
end;
@@ -578,7 +578,7 @@ begin
end;
For I:=0 to InputFiles.Count-1 do
begin
- Engine := TClassTreeEngine.Create(XML,AObjectKind);
+ Engine := TClassTreeEngine.Create(XML,[AObjectKind]);
Try
ParseSource(Engine,InputFiles[I],OSTarget,CPUTarget);
Engine.Ftree.BuildTree(Engine.FObjects);
diff --git a/avx512-0037785/utils/fpdoc/fpdoc.lpi b/avx512-0037785/utils/fpdoc/fpdoc.lpi
index b9c99b0c3f..201f6383a8 100644
--- a/avx512-0037785/utils/fpdoc/fpdoc.lpi
+++ b/avx512-0037785/utils/fpdoc/fpdoc.lpi
@@ -8,6 +8,7 @@
<SaveOnlyProjectUnits Value="True"/>
<MainUnitHasCreateFormStatements Value="False"/>
<MainUnitHasTitleStatement Value="False"/>
+ <MainUnitHasScaledStatement Value="False"/>
<SaveJumpHistory Value="False"/>
<SaveFoldState Value="False"/>
<CompatibilityMode Value="True"/>
@@ -46,7 +47,7 @@
<PackageName Value="FCL"/>
</Item1>
</RequiredPackages>
- <Units Count="20">
+ <Units Count="21">
<Unit0>
<Filename Value="fpdoc.pp"/>
<IsPartOfProject Value="True"/>
@@ -134,6 +135,10 @@
<Filename Value="dw_basehtml.pp"/>
<IsPartOfProject Value="True"/>
</Unit19>
+ <Unit20>
+ <Filename Value="fpdocstrs.pp"/>
+ <IsPartOfProject Value="True"/>
+ </Unit20>
</Units>
</ProjectOptions>
<CompilerOptions>
@@ -143,13 +148,22 @@
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/>
+ <OtherUnitFiles Value="../../packages/fcl-passrc/src"/>
<UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Linking>
<Debugging>
<DebugInfoType Value="dsDwarf3"/>
+ <UseHeaptrc Value="True"/>
</Debugging>
</Linking>
+ <Other>
+ <CustomOptions Value="-dCheckPasTreeRefCountx
+-dDebugRefCountx"/>
+ <OtherDefines Count="1">
+ <Define0 Value="CheckPasTreeRefCount"/>
+ </OtherDefines>
+ </Other>
</CompilerOptions>
<Debugging>
<Exceptions Count="3">
diff --git a/avx512-0037785/utils/fpdoc/fpdoc.pp b/avx512-0037785/utils/fpdoc/fpdoc.pp
index 5e789409e1..abbc8863d8 100644
--- a/avx512-0037785/utils/fpdoc/fpdoc.pp
+++ b/avx512-0037785/utils/fpdoc/fpdoc.pp
@@ -14,7 +14,8 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
}
-
+{$mode objfpc}
+{$h+}
program FPDoc;
uses
@@ -37,7 +38,7 @@ uses
dw_man, // Man page writer
dw_linrtf, // linear RTF writer
dw_txt, // TXT writer
- fpdocproj, mkfpdoc, dw_basemd, dw_basehtml;
+ fpdocproj, mkfpdoc, dw_basemd, dw_basehtml, fpdocstrs;
Type
@@ -101,9 +102,14 @@ begin
Writeln(SUsageOption190);
Writeln(SUsageOption200);
Writeln(SUsageOption210);
+ Writeln(SUsageOption211);
+ Writeln(SUsageOption212);
Writeln(SUsageOption215);
Writeln(SUsageOption215A);
Writeln(SUsageOption220);
+ Writeln(SUsageOption221);
+ Writeln(SUsageOption222);
+ Writeln(SUsageOption223);
Writeln(SUsageOption230);
Writeln(SUsageOption240);
Writeln(SUsageOption250);
@@ -151,7 +157,11 @@ end;
procedure TFPDocApplication.ExceptProc(Sender: TObject; E: Exception);
begin
+ OutputLog(Sender, Format('Exception: Class - %s', [E.ClassName]));
+ OutputLog(Sender, E.Message);
+{$IFDEF EXCEPTION_STACK}
OutputLog(Sender, DumpExceptionCallStack(E));
+{$ENDIF}
end;
destructor TFPDocApplication.Destroy;
@@ -305,8 +315,16 @@ begin
Usage(0)
else if s = '--hide-protected' then
FCreator.Options.HideProtected := True
+ else if s = '--fallback-seealso-links' Then
+ FCreator.Options.FallBackSeeAlsoLinks := True
else if s = '--warn-no-node' then
FCreator.Options.WarnNoNode := True
+ else if s = '--warn-documentation-empty' then
+ FCreator.Options.WarnDocumentationEmpty := True
+ else if s = '--info-used-file' then
+ FCreator.Options.InfoUsedFile := True
+ else if s = '--warn-XCT' then
+ FCreator.Options.WarnXCT := True
else if s = '--show-private' then
FCreator.Options.ShowPrivate := True
else if s = '--stop-on-parser-error' then
@@ -430,15 +448,15 @@ end;
constructor TFPDocApplication.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
- StopOnException:=true;
+ StopOnException:=false;
FCreator:=TFPDocCreator.Create(Self);
FCreator.OnLog:=@OutputLog;
OnException:= @ExceptProc;
end;
begin
- //AssignFile(Output, 'fpdoc.log');
- //rewrite(Output);
+ //AssignFile(StdErr, 'fpdoc_err.log');
+ //rewrite(StdErr);
With TFPDocApplication.Create(Nil) do
try
Run;
diff --git a/avx512-0037785/utils/fpdoc/fpdocclasstree.pp b/avx512-0037785/utils/fpdoc/fpdocclasstree.pp
index 3ea8c84d65..2dc99839ba 100644
--- a/avx512-0037785/utils/fpdoc/fpdocclasstree.pp
+++ b/avx512-0037785/utils/fpdoc/fpdocclasstree.pp
@@ -2,6 +2,7 @@ unit fpdocclasstree;
{$mode objfpc}{$H+}
+
interface
uses
@@ -9,21 +10,23 @@ uses
Type
+ TPasObjKindSet = set of TPasObjKind;
+
{ TPasElementNode }
TPasElementNode = Class
Private
- FElement : TPasClassType;
+ FElement : TPasType;
FParentNode: TPasElementNode;
FChildren : TFPObjectList;
function GetChild(aIndex : Integer): TPasElementNode;
function GetChildCount: Integer;
Public
- Constructor Create (aElement : TPasClassType);
+ Constructor Create (aElement : TPasType);
Destructor Destroy; override;
Procedure AddChild(C : TPasElementNode);
Procedure SortChildren;
- Property Element : TPasClassType Read FElement;
+ Property Element : TPasType Read FElement;
Property ParentNode : TPasElementNode read FParentNode;
Property Children [aIndex : Integer] : TPasElementNode Read GetChild;
Property ChildCount : Integer Read GetChildCount;
@@ -35,17 +38,17 @@ Type
Private
FEngine:TFPDocEngine;
FElementList : TFPObjectHashTable;
- FObjectKind : TPasObjKind;
+ FObjectKind : TPasObjKindSet;
FPackage: TPasPackage;
FParentObject : TPasClassType;
FRootNode : TPasElementNode;
FRootObjectName : string;
FRootObjectPathName : string;
Protected
- function AddToList(aElement: TPasClassType): TPasElementNode;
+ function AddToList(aElement: TPasType): TPasElementNode;
Public
Constructor Create(AEngine:TFPDocEngine; APackage : TPasPackage;
- AObjectKind : TPasObjKind = okClass);
+ AObjectKind : TPasObjKindSet = okWithFields);
Destructor Destroy; override;
Function BuildTree(AObjects : TStringList) : Integer;
Procedure SaveToXml(AFileName: String);
@@ -56,6 +59,9 @@ Type
implementation
+uses
+ fpdocstrs, pasresolver;
+
{ TPasElementNode }
function SortOnElementName(Item1, Item2: Pointer): Integer;
@@ -79,7 +85,7 @@ begin
Result:=0
end;
-constructor TPasElementNode.Create(aElement: TPasClassType);
+constructor TPasElementNode.Create(aElement: TPasType);
begin
FElement:=aElement;
end;
@@ -104,33 +110,36 @@ begin
end;
constructor TClassTreeBuilder.Create(AEngine:TFPDocEngine; APackage : TPasPackage;
- AObjectKind: TPasObjKind);
+ AObjectKind: TPasObjKindSet);
begin
FEngine:= AEngine;
FPackage:= APAckage;
FObjectKind:=AObjectKind;
- Case FObjectkind of
- okInterface :
+ if (okInterface in FObjectkind) then
begin
FRootObjectPathName:='#rtl.System.IInterface';
FRootObjectName:= 'IInterface';
- end;
- okObject, okClass :
+ end
+ else if (FObjectkind * okWithFields) <> [] then
begin
FRootObjectPathName:='#rtl.System.TObject';
FRootObjectName:= 'TObject';
end
- else
+ else // TODO: I don`t know need it ? Without that the code may be simplified.
begin
FRootObjectPathName:='#rtl.System.TObject';
FRootObjectName:= 'TObject';
end;
- end;
FParentObject:=TPasClassType.Create(FRootObjectName,FEngine.FindModule('System'));
if not Assigned(FParentObject) then
FParentObject:=TPasClassType.Create(FRootObjectName,FPackage);
- FParentObject.ObjKind:=FObjectKind;
+ if (okInterface in FObjectkind) then
+ FParentObject.ObjKind:=okInterface
+ else if (FObjectkind * okWithFields) <> [] then
+ FParentObject.ObjKind:=okClass
+ else
+ FParentObject.ObjKind:=okClass;
FRootNode:=TPasElementNode.Create(FParentObject);
FRootNode.FParentNode := nil;
FElementList:=TFPObjectHashTable.Create(False);
@@ -145,29 +154,42 @@ begin
Inherited;
end;
-function TClassTreeBuilder.AddToList ( aElement: TPasClassType
+function TClassTreeBuilder.AddToList ( aElement: TPasType
) : TPasElementNode;
Var
aParentNode : TPasElementNode;
aName : String;
+ aElementClass: TPasClassType;
begin
- Result:= nil;
- if (aElement.ObjKind <> FObjectKind) then exit;
+ Result:= nil; aElementClass:=nil;
+ if (aElement is TPasClassType) then
+ aElementClass:= TPasClassType(aElement);
+ if Assigned(aElementClass) and not (aElementClass.ObjKind in FObjectKind) then exit;
+ if not Assigned(aElementClass) and not (aElement is TPasAliasType) then exit;
+
aParentNode:= nil;
if aElement=Nil then
aName:=FRootObjectName
+ else if (aElement is TPasAliasType) then
+ aName:=TPasAliasType(aElement).DestType.FullName
else
aName:=aElement.PathName;
Result:=TPasElementNode(FElementList.Items[aName]);
if (Result=Nil) then
begin
- if aElement.AncestorType is TPasClassType then
- aParentNode:=AddToList(aElement.AncestorType as TPasClassType);
+ if Assigned(aElementClass) and (
+ (aElementClass.AncestorType is TPasClassType) or
+ (aElementClass.AncestorType is TPasAliasType)
+ ) then
+ aParentNode:=AddToList(aElementClass.AncestorType);
if not Assigned(aParentNode) then
aParentNode:=FRootNode;
- Result:=TPasElementNode.Create(aElement);
+ if (aElement is TPasAliasType) then
+ Result:=TPasElementNode.Create(TPasAliasType(TPasType(aElement)).DestType)
+ else
+ Result:=TPasElementNode.Create(aElement);
aParentNode.AddChild(Result);
Result.FParentNode := aParentNode;
FElementList.Add(aName,Result);
@@ -227,10 +249,11 @@ procedure TClassTreeBuilder.SaveToXml ( AFileName: String );
for CounterVar := 0 to ParentPasEl.ChildCount-1 do
begin
PasElNode:= ParentPasEl.Children[CounterVar];
- xmlEl:= AXmlDoc.CreateElement(UnicodeString(PasElNode.Element.Name));
+ xmlEl:= AXmlDoc.CreateElement(UTF8Decode(PasElNode.Element.Name));
M:= PasElNode.Element.GetModule;
- xmlEl['unit'] := UnicodeString(M.Name);
- xmlEl['package'] := UnicodeString(M.PackageName);
+ xmlEl['unit'] := UTF8Decode(M.Name);
+ xmlEl['package'] := UTF8Decode(M.PackageName);
+ xmlEl['type'] := UTF8Decode(GetElementTypeName(PasElNode.Element));
ParentxmlEl.AppendChild(xmlEl);
AddPasElChildsToXml(xmlEl, PasElNode);
end;
@@ -244,17 +267,24 @@ begin
XmlDoc:= TXMLDocument.Create;
XmlDoc.AppendChild(XmlDoc.CreateComment(UTF8Decode(SDocGeneratedByComment)));
try
- XmlRootEl:= XmlDoc.CreateElement(UnicodeString(FRootNode.Element.Name));
+ XmlRootEl:= XmlDoc.CreateElement(UTF8Decode(FRootNode.Element.Name));
M:= FRootNode.Element.GetModule;
if Assigned(M) then
begin
- XmlRootEl['unit'] := UnicodeString(M.Name);
- XmlRootEl['package'] := UnicodeString(M.PackageName);
+ XmlRootEl['unit'] := UTF8Decode(M.Name);
+ XmlRootEl['package'] := UTF8Decode(M.PackageName);
+ XmlRootEl['type'] := UTF8Decode(GetElementTypeName(FRootNode.Element));
end
else
begin
XmlRootEl['unit'] := 'system';
XmlRootEl['package'] := 'rtl';
+ if (okWithFields * FObjectKind) <> [] then
+ XmlRootEl['type'] := 'class'
+ else if (okInterface in FObjectKind) then
+ XmlRootEl['type'] := 'interface'
+ else
+ XmlRootEl['type'] := 'class';
end;
XmlDoc.AppendChild(XmlRootEl);
AddPasElChildsToXml(XmlRootEl, FRootNode);
diff --git a/avx512-0037785/utils/fpdoc/fpdocproj.pas b/avx512-0037785/utils/fpdoc/fpdocproj.pas
index 7ea90f3401..7ab8020431 100644
--- a/avx512-0037785/utils/fpdoc/fpdocproj.pas
+++ b/avx512-0037785/utils/fpdoc/fpdocproj.pas
@@ -55,13 +55,17 @@ Type
FFormat: String;
FHidePrivate: Boolean;
FHideProtected: Boolean;
+ FFallBackSeeAlsoLinks: Boolean;
FIO: Boolean;
FLanguage: String;
FMoDir: String;
FOSTarget: String;
FSOPE: Boolean;
+ FWarnDocumentationEmpty: Boolean;
FWarnNoNode: Boolean;
FDontTrim : Boolean;
+ FInfoUsedFile: Boolean;
+ FWarnXCT: Boolean;
procedure SetBackendOptions(const AValue: TStrings);
Public
Constructor Create;
@@ -76,7 +80,11 @@ Type
Property BackendOptions : TStrings Read FBackEndoptions Write SetBackendOptions;
Property StopOnParseError : Boolean Read FSOPE Write FSOPE;
Property HideProtected : Boolean Read FHideProtected Write FHideProtected;
+ Property FallBackSeeAlsoLinks :Boolean Read FFallBackSeeAlsoLinks Write FFallBackSeeAlsoLinks;
Property WarnNoNode : Boolean Read FWarnNoNode Write FWarnNoNode;
+ Property InfoUsedFile : Boolean Read FInfoUsedFile Write FInfoUsedFile;
+ Property WarnDocumentationEmpty : Boolean Read FWarnDocumentationEmpty Write FWarnDocumentationEmpty;
+ Property WarnXCT : Boolean Read FWarnXCT Write FWarnXCT;
Property ShowPrivate : Boolean Read FHidePrivate Write FHidePrivate;
Property InterfaceOnly : Boolean Read FIO Write FIO;
Property MoDir : String Read FMoDir Write FMODir;
@@ -189,6 +197,9 @@ begin
FSOPE:=O.StopOnParseError;
HideProtected:=O.HideProtected;
WarnNoNode:=O.WarnNoNode;
+ InfoUsedFile:=O.InfoUsedFile;
+ WarnDocumentationEmpty:=O.WarnDocumentationEmpty;
+ WarnXCT:=O.WarnXCT;
ShowPrivate:=O.ShowPrivate;
InterfaceOnly:=O.InterfaceOnly;
MoDir:=O.MoDir;
diff --git a/avx512-0037785/utils/fpdoc/fpdocstrs.pp b/avx512-0037785/utils/fpdoc/fpdocstrs.pp
new file mode 100644
index 0000000000..2e58cf64f4
--- /dev/null
+++ b/avx512-0037785/utils/fpdoc/fpdocstrs.pp
@@ -0,0 +1,256 @@
+unit fpdocstrs;
+
+{$mode objfpc}{$H+}
+
+interface
+
+resourcestring
+ // Output strings
+ SDocPackageTitle = 'Reference for package ''%s''';
+ SDocPackageMenuTitle = 'Package ''%s''';
+ SDocPackageLinkTitle = 'Package';
+ SDocPrograms = 'Programs';
+ SDocUnits = 'Units';
+ SDocUnitTitle = 'Reference for unit ''%s''';
+ SDocUnitMenuTitle = 'Unit ''%s''';
+ SDocInheritanceHierarchy = 'Inheritance Hierarchy';
+ SDocInterfaceSection = 'Interface section';
+ SDocImplementationSection = 'Implementation section';
+ SDocUsedUnits = 'Used units';
+ SDocUsedUnitsByUnitXY = 'Used units by unit ''%s''';
+ SDocConstsTypesVars = 'Constants, types and variables';
+ SDocResStrings = 'Resource strings';
+ SDocTypes = 'Types';
+ SDocType = 'Type';
+ SDocConstants = 'Constants';
+ SDocConstant = 'Constant';
+ SDocClasses = 'Classes';
+ SDocClass = 'Class';
+ SDocProceduresAndFunctions = 'Procedures and functions';
+ SDocProcedureOrFunction = 'Procedure/function';
+ SDocVariables = 'Variables';
+ SDocVariable = 'Variable';
+ SDocIdentifierIndex = 'Index';
+ SDocPackageClassHierarchy = 'Class hierarchy';
+ SDocModuleIndex = 'Index of all identifiers in unit ''%s''';
+ SDocPackageIndex = 'Index of all identifiers in package ''%s''';
+ SDocUnitOverview = 'Overview of unit ''%s''';
+ SDocOverview = 'Overview';
+ SDocSearch = 'Search';
+ SDocDeclaration = 'Declaration';
+ SDocDescription = 'Description';
+ SDocErrors = 'Errors';
+ SDocVersion = 'Version info';
+ SDocSeeAlso = 'See also';
+ SDocExample = 'Example';
+ SDocArguments = 'Arguments';
+ SDocFunctionResult = 'Function result';
+ SDocRemark = 'Remark: ';
+ SDocMethodOverview = 'Method overview';
+ SDocPropertyOverview = 'Property overview';
+ SDocEventOverview = 'Event overview';
+ SDocInterfacesOverview = 'Interfaces overview';
+ SDocInterface = 'Interfaces';
+ SDocPage = 'Page';
+ SDocMember = 'Member';
+ SDocMembers = 'Members';
+ SDocField = 'Field';
+ SDocMethod = 'Method';
+ SDocProperty = 'Property';
+ SDocAccess = 'Access';
+ SDocInheritance = 'Inheritance';
+ SDocProperties = 'Properties';
+ SDocMethods = 'Methods';
+ SDocEvents = 'Events';
+ SDocByName = 'by Name';
+ SDocByInheritance = 'By inheritance';
+ SDocValue = 'Value';
+ SDocExplanation = 'Explanation';
+ SDocProcedure = 'Procedure';
+ SDocValuesForEnum = 'Enumeration values for type %s';
+ SDocSourcePosition = 'Source position: %s line %d';
+ SDocSynopsis = 'Synopsis';
+ SDocVisibility = 'Visibility';
+ SDocOpaque = 'Opaque type';
+ SDocDateGenerated = 'Documentation generated on: %s';
+ // The next line requires leading/trailing space due to XML comment layout:
+ SDocGeneratedByComment = ' Generated using FPDoc - (c) 2000-2021 FPC contributors and Sebastian Guenther, sg@freepascal.org ';
+ SDocNotes = 'Notes';
+ SDocName = 'Name';
+ SDocType_s = 'Type(s)';
+ SDocTopic = 'Topic';
+ SDocNoneAVailable = 'No members available';
+
+ // Topics
+ SDocRelatedTopics = 'Related topics';
+ SDocUp = 'Up';
+ SDocNext = 'Next';
+ SDocPrevious = 'Previous';
+
+ // Various backend constants
+ SDocChapter = 'Chapter';
+ SDocSection = 'Section';
+ SDocSubSection = 'Subsection';
+ SDocTable = 'Table';
+ SDocListing = 'Listing';
+
+ // Man page usage
+ SManUsageManSection = 'Use ASection as the man page section';
+ SManUsageNoUnitPrefix = 'Do not prefix man pages with unit name.';
+ SManUsageWriterDescr = 'UNIX man page output.';
+ SManUsagePackageDescription = 'Use descr as the description of man pages';
+
+ // HTML usage
+ SHTMLUsageFooter = 'Append xhtml (@filename reads from file) as footer to html page';
+ SHTMLUsageNavigator = 'Append xhtml (@filename reads from file) in navigator bar';
+ SHTMLUsageHeader = 'Append xhtml (@filename reads from file) as header to html page below navigation bar';
+ SHTMLUsageFooterDate = 'Append footer with date. fmt is Optional format for FormatDateTime';
+ SHTMLUsageCharset = 'Set the HTML character set';
+ SHTMLHtmlSearch = 'Add search page with given name to the menu bar';
+ SHTMLIndexColcount = 'Use N columns in the identifier index pages';
+ SHTMLImageUrl = 'Prefix image URLs with url';
+ SHTMLDisableMenuBrackets = 'Disable ''['' and '']'' characters around menu items at the top of the page. Useful for custom css';
+
+ // CHM usage
+ SCHMUsageTOC = 'Use [File] as the table of contents. Usually a .hhc file.';
+ SCHMUsageIndex = 'Use [File] as the index. Usually a .hhk file.';
+ SCHMUsageDefPage = 'Set the "Home" page relative to where it lives in the chm. i.e. "/index.html"';
+ SCHMUsageOtrFiles= 'A txt file containing a list of files to be added relative to the working directory.';
+ SCHMUsageCSSFile = 'Filename of a .css file to be included in the chm.';
+ SCHMUsageAutoTOC = 'Automatically generate a Table of Contents. Ignores --toc-file';
+ SCHMUsageAutoIDX = 'Automatically generate an Index. Ignores --index-file';
+ SCHMUsageMakeSearch = 'Automatically generate a Search Index from filenames that match *.htm*';
+ SCHMUsageChmTitle= 'Title of the chm. Defaults to the value from --package';
+
+ // MarkDown usage
+ SMDUsageFooter = 'Append markdown (@filename reads from file) as footer to every markdown page';
+ SMDUsageHeader = 'Prepend markdown (@filename reads from file) as header to every markdown page';
+ SMDIndexColcount = 'Use N columns in the identifier index pages';
+ SMDImageUrl = 'Prefix image URLs with url';
+ SMDTheme = 'Use name as theme name';
+ SMDNavigation = 'Use scheme for navigation tree, here scheme is one of:';
+ SMDNavSubtree = ' UnitSubTree : put all units in a sub tree of a Units node';
+ SMDNavTree = ' UnitTree : put every units as a node on the same level as packages node';
+
+ SXMLUsageFlatStructure = 'Use a flat output structure of XML files and directories';
+ SXMLUsageSource = 'Include source file and line info in generated XML';
+
+ // Linear usage
+ SLinearUsageDupLinkedDocsP1 = 'Duplicate linked element documentation in';
+ SLinearUsageDupLinkedDocsP2 = 'descendant classes.';
+
+ STitle = 'FPDoc - Free Pascal Documentation Tool';
+ SVersion = 'Version %s [%s]';
+ SCopyright1 = '(c) 2000 - 2003 Areca Systems GmbH / Sebastian Guenther, sg@freepascal.org';
+ SCopyright2 = '(c) 2005 - 2021 various FPC contributors';
+
+ SCmdLineHelp = 'Usage: %s [options]';
+ SUsageOption008 = '--base-descr-dir=DIR prefix all description files with this directory';
+ SUsageOption009 = '--base-input-dir=DIR prefix all input files with this directory';
+ SUsageOption010 = '--content Create content file for package cross-references';
+ SUsageOption020 = '--cputarget=value Set the target CPU for the scanner.';
+ SUsageOption030 = '--descr=file use file as description file, e.g.: ';
+ SUsageOption035 = ' --descr=c:\WIP\myzipperdoc.xml';
+ SUsageOption040 = ' This option is allowed more than once';
+ SUsageOption050 = '--descr-dir=Dir Add All XML files in Dir to list of description files';
+ SUsageOption060 = '--format=fmt Select output format.';
+ SUsageOption070 = '--help Show this help.';
+ SUsageOption080 = '--hide-protected Do not show protected methods in overview';
+ SUsageOption090 = '--import=file Import content file for package cross-references';
+ SUsageOption100 = '--input=cmd use cmd as input for the parser, e.g.:';
+ SUsageOption110 = ' --input=C:\fpc\packages\paszlib\src\zipper.pp';
+ SUsageOption120 = ' At least one input option is required.';
+ SUsageOption130 = '--input-dir=Dir Add All *.pp and *.pas files in Dir to list of input files';
+ SUsageOption140 = '--lang=lng Select output language.';
+ SUsageOption145 = '--macro=name=value Define a macro to preprocess the project file with.';
+ SUsageOption150 = '--ostarget=value Set the target OS for the scanner.';
+ SUsageOption160 = '--output=name use name as the output name.';
+ SUsageOption170 = ' Each backend interprets this as needed.';
+ SUsageOption180 = '--package=name Set the package name for which to create output,';
+ SUsageOption190 = ' e.g. --package=fcl';
+ SUsageOption200 = '--project=file Use file as project file';
+ SUsageOption210 = '--show-private Show private methods.';
+ SUsageOption211 = '--fallback-seealso-links';
+ SUsageOption212 = ' Simplify seealso links by exluding last link level';
+ SUsageOption215 = '--stop-on-parser-error';
+ SUsageOption215A = ' Stop when a parser error occurs. Default is to ignore parser errors.';
+ SUsageOption220 = '--warn-no-node Warn if no documentation node was found.';
+ SUsageOption221 = '--warn-documentation-empty Warn if documentation is empty.';
+ SUsageOption222 = '--warn-xct Warn if an external class could not be resolved.';
+ SUsageOption223 = '--info-used-file Output the file path of an implicitly processed file.';
+ SUsageOption230 = '--mo-dir=dir Set directory where language files reside to dir';
+ SUsageOption240 = '--parse-impl (Experimental) try to parse implementation too';
+ SUsageOption250 = '--dont-trim Do not trim XML contents. Useful for preserving';
+ SUsageOption260 = ' formatting inside e.g <pre> tags';
+ SUsageOption270 = '--write-project=file';
+ SUsageOption280 = ' Do not write documentation, create project file instead';
+ SUsageOption290 = '--verbose Write more information on the screen';
+ SUsageOption300 = '--dry-run Only parse sources and XML, do not create output';
+ SUsageOption310 = '--write-project=file';
+ SUsageOption320 = ' Write all command-line options to a project file';
+ SUsageSubNames = 'Use the file subnames instead the indexes as postfixes';
+ SUsageOnlyPages = 'Only write pages in LIST, LIST is comma-separated list of filenames or @filename where the named file contains 1 file per line.';
+
+ SUsageFormats = 'The following output formats are supported by this fpdoc:';
+ SUsageBackendHelp = 'Specify an output format, combined with --help to get more help for this backend.';
+ SUsageFormatSpecific = 'Output format "%s" supports the following options:';
+ SCmdLineErrInvalidMacro = 'Macro needs to be in the form name=value';
+
+ SCmdLineInvalidOption = 'Ignoring unknown option "%s"';
+ SCmdLineInvalidFormat = 'Invalid format "%s" specified';
+ SCmdLineOutputOptionMissing = 'Need an output filename, please specify one with --output=<filename>';
+ SWritingPages = 'Writing %d pages...';
+ SNeedPackageName = 'No package name specified. Please specify one using the --package option.';
+ SAvailablePackages = 'Available packages: ';
+ SDone = 'Done.';
+ SErrCouldNotCreateOutputDir = 'Could not create output directory "%s"';
+ SErrCouldNotCreateFile = 'Could not create file "%s": %s';
+ SSeeURL = '(See %s)'; // For linear text writers.
+ SParsingUsedUnit = 'Parsing used unit "%s" with commandLine "%s"';
+
+ SErrFileWriting = 'An error occurred during writing of file "%s": %s';
+
+ SErrInvalidShortDescr = 'Invalid short description';
+ SErrInvalidDescr = 'Invalid description (illegal XML element: "%s")';
+ SErrInvalidParaContent = 'Invalid paragraph content';
+ SErrInvalidElementInList = 'Invalid element in list - only "li" allowed';
+ SErrInvalidListContent = 'Invalid list content';
+ SErrInvalidRemarkContent = 'Invalid <remark> content (illegal XML element: "%s")';
+ SErrListIsEmpty = 'List is empty - need at least one "li" element';
+ SErrInvalidDefinitionTermContent = 'Invalid content in definition term';
+ SErrDefinitionEntryMissing = 'Definition entry after definition term is missing';
+ SErrInvalidBorderValue = 'Invalid "border" value for %s';
+ SErrInvalidTableContent = 'Invalid table content';
+ SErrTableRowEmpty = 'Table row is empty (no "td" elements found)';
+ SErrInvalidContentBeforeSectionTitle = 'Invalid content before section title';
+ SErrSectionTitleExpected = 'Section title ("title" element) expected';
+
+ SErrDescrTagUnknown = 'Warning: Unknown tag "%s" in description';
+ SErrUnknownEntityReference = 'Warning: Unknown entity reference "&%s;" found';
+ SErrUnknownLinkID = 'Warning: Target ID of <link> in unit "%s", element "%s", is unknown: "%s"';
+ SErrUnknownPrintShortID = 'Warning: Target ID of <printshort> is unknown: "%s"';
+ SErrUnknownLink = 'Could not resolve link to "%s"';
+ SErralreadyRegistered = 'Class for output format "%s" already registered';
+ SErrUnknownWriterClass = 'Unknown output format "%s"';
+
+ SErrCannotChangeIndentSizeWhenIndented = 'Cannot change indent size while text is indented.';
+ SErrIndentMismatch = 'Indent mismatch: trying to undent when current indent too small';
+ SErrNotInList = 'Not in list';
+ SErrPopListStack = 'Pop list stack list type mismatch';
+ SErrMinListStack = 'Min list stack reached';
+ SErrMaxListStack = 'Max list stack reached';
+ SErrMinIndentStack = 'Min indent stack reached';
+ SErrMaxIndentStack = 'Max indent stack reached';
+
+ // doc xml
+ SErrInvalidRootNode = 'Invalid options root node: Got "%s", expected "docproject"';
+ SErrNoPackagesNode = 'No "packages" node found in docproject';
+ SErrNoInputFile = 'unit tag without file attribute found';
+ SErrNoDescrFile = 'description tag without file attribute';
+ SErrNoImportFile = 'Import tag without file attribute';
+ SErrNoImportPrefix = 'Import tag without prefix attribute';
+
+implementation
+
+end.
+
diff --git a/avx512-0037785/utils/fpdoc/fpdocxmlopts.pas b/avx512-0037785/utils/fpdoc/fpdocxmlopts.pas
index b3897af126..c2fe4d25fe 100644
--- a/avx512-0037785/utils/fpdoc/fpdocxmlopts.pas
+++ b/avx512-0037785/utils/fpdoc/fpdocxmlopts.pas
@@ -44,15 +44,8 @@ Const
implementation
-Uses XMLRead, XMLWrite;
-
-Resourcestring
- SErrInvalidRootNode = 'Invalid options root node: Got "%s", expected "docproject"';
- SErrNoPackagesNode = 'No "packages" node found in docproject';
- SErrNoInputFile = 'unit tag without file attribute found';
- SErrNoDescrFile = 'description tag without file attribute';
- SErrNoImportFile = 'Import tag without file attribute';
- SErrNoImportPrefix = 'Import tag without prefix attribute';
+Uses fpdocstrs, XMLRead, XMLWrite;
+
{ TXMLFPDocOptions }
diff --git a/avx512-0037785/utils/fpdoc/fpmake.pp b/avx512-0037785/utils/fpdoc/fpmake.pp
index 1dabb89934..0ae4354525 100644
--- a/avx512-0037785/utils/fpdoc/fpmake.pp
+++ b/avx512-0037785/utils/fpdoc/fpmake.pp
@@ -42,6 +42,7 @@ begin
P.Options.Add('-S2h');
T:=P.Targets.AddProgram('fpdoc.pp');
+ T.Dependencies.AddUnit('fpdocstrs');
T.Dependencies.AddUnit('dglobals');
T.Dependencies.AddUnit('dw_ipflin');
T.Dependencies.AddUnit('dwriter');
@@ -65,17 +66,18 @@ begin
T:=P.Targets.AddProgram('fpclasschart.pp');
T.ResourceStrings:=true;
- T := P.Targets.AddUnit('dglobals.pp');
+ T := P.Targets.AddUnit('fpdocstrs.pp');
T.install:=false;
T.ResourceStrings:=true;
+ T := P.Targets.AddUnit('dglobals.pp');
+ T.install:=false;
+
T := P.Targets.AddUnit('dwriter.pp');
T.install:=false;
- T.ResourceStrings:=true;
T := P.Targets.AddUnit('fpdocxmlopts.pas');
T.install:=false;
- T.ResourceStrings:=true;
P.Targets.AddUnit('dw_xml.pp').install:=false;
P.Targets.AddUnit('sh_pas.pp').install:=false;
@@ -84,7 +86,7 @@ begin
P.Targets.AddUnit('dw_markdown.pp').install:=false;
T:=P.Targets.AddUnit('dw_latex.pp');
T.install:=false;
- T.ResourceStrings:=true;
+
P.Targets.AddUnit('dw_txt.pp').install:=false;
P.Targets.AddUnit('dw_man.pp').install:=false;
P.Targets.AddUnit('dwlinear.pp').install:=false;
diff --git a/avx512-0037785/utils/fpdoc/makeskel.pp b/avx512-0037785/utils/fpdoc/makeskel.pp
index 23c3daf2d4..3d0b637f29 100644
--- a/avx512-0037785/utils/fpdoc/makeskel.pp
+++ b/avx512-0037785/utils/fpdoc/makeskel.pp
@@ -23,7 +23,7 @@ program MakeSkel;
{$h+}
uses
- SysUtils, Classes, Gettext, dGlobals, PasTree, PParser,PScanner;
+ fpdocstrs, SysUtils, Classes, Gettext, dGlobals, PasTree, PParser,PScanner;
resourcestring
STitle = 'MakeSkel - FPDoc skeleton XML description file generator';
diff --git a/avx512-0037785/utils/fpdoc/mkfpdoc.pp b/avx512-0037785/utils/fpdoc/mkfpdoc.pp
index 019369425b..8b1b3cfa52 100644
--- a/avx512-0037785/utils/fpdoc/mkfpdoc.pp
+++ b/avx512-0037785/utils/fpdoc/mkfpdoc.pp
@@ -34,6 +34,7 @@ Type
FProjectMacros: TStrings;
FScannerLogEvents: TPScannerLogEvents;
FVerbose: Boolean;
+ function GetLogLevels: TFPDocLogLevels;
function GetOptions: TEngineOptions;
function GetPackages: TFPDocPackages;
procedure SetBaseDescrDir(AValue: String);
@@ -73,6 +74,7 @@ Type
implementation
+uses fpdocstrs;
{ TFPDocCreator }
@@ -84,6 +86,9 @@ begin
begin
ScannerLogEvents:=[sleFile];
ParserLogEvents:=[];
+ Options.InfoUsedFile:= true;
+ Options.WarnDocumentationEmpty:= true;
+ Options.WarnXCT:= true;
end
else
begin
@@ -243,8 +248,8 @@ begin
If not InterPretOption(Cmd,Arg) then
DoLog(SCmdLineInvalidOption,[Cmd+'='+Arg]);
end;
- // Output created Documentation
- WriteDoc;
+ // Create documentation by writer
+ WriteDocumentation();
Finally
Free;
end;
@@ -255,6 +260,23 @@ begin
Engine.WriteContentFile(APackage.ContentFile);
end;
+Function TFPDocCreator.GetLogLevels : TFPDocLogLevels;
+
+ Procedure DoOpt(doSet : Boolean; aLevel: TFPDocLogLevel);
+
+ begin
+ if DoSet then
+ Result:=Result+[aLevel];
+ end;
+
+begin
+ Result:=[];
+ DoOpt(Options.WarnNoNode,dleWarnNoNode);
+ DoOpt(Options.InfoUsedFile,dleWarnUsedFile);
+ DoOpt(Options.WarnDocumentationEmpty,dleDocumentationEmpty);
+ DoOpt(Options.WarnXCT,dleXCT);
+end;
+
procedure TFPDocCreator.CreateDocumentation(APackage: TFPDocPackage;
ParseOnly: Boolean);
@@ -263,7 +285,7 @@ var
Engine : TFPDocEngine;
Cmd,Arg : String;
WriterClass: TFPDocWriterClass;
-
+ eMsg: String;
begin
Cmd:='';
FCurPackage:=APackage;
@@ -291,35 +313,53 @@ begin
Engine.HideProtected:=Options.HideProtected;
Engine.HidePrivate:=Not Options.ShowPrivate;
Engine.OnParseUnit:=@HandleOnParseUnit;
- Engine.WarnNoNode:=Options.WarnNoNode;
+ Engine.DocLogLevels:=GetLogLevels;
+ Engine.FalbackSeeAlsoLinks:= Options.FallBackSeeAlsoLinks;
if Length(Options.Language) > 0 then
TranslateDocStrings(Options.Language);
// scan the input source files
for i := 0 to APackage.Inputs.Count - 1 do
try
- // get options from input packages
- SplitInputFileOption(APackage.Inputs[i],Cmd,Arg);
- arg:=Arg+' -d'+Options.EndianNess;
- // make absolute filepath
- Cmd:=FixInputFile(Cmd);
- if FProcessedUnits.IndexOf(Cmd)=-1 then
+ try
+ eMsg:='';
+ // get options from input packages
+ SplitInputFileOption(APackage.Inputs[i],Cmd,Arg);
+ arg:=Arg+' -d'+Options.EndianNess;
+ // make absolute filepath
+ Cmd:=FixInputFile(Cmd);
+ if FProcessedUnits.IndexOf(Cmd)=-1 then
begin
- FProcessedUnits.Add(Cmd);
-
- // Parce sources for OS Target
- //WriteLn(Format('Parsing unit: %s', [ExtractFilenameOnly(Cmd)]));
- ParseSource(Engine,Cmd+' '+Arg, Options.OSTarget, Options.CPUTarget,[poUseStreams]);
+ FProcessedUnits.Add(Cmd);
+ // Parce sources for OS Target
+ //WriteLn(Format('Parsing unit: %s', [ExtractFilenameOnly(Cmd)]));
+ ParseSource(Engine,Cmd+' '+Arg, Options.OSTarget, Options.CPUTarget,[poUseStreams]); // poSkipDefaultDefs
end;
- except
- on E: EParserError do
- If Options.StopOnParseError then
- Raise
- else
+ //else WriteLn(Format('Processed unit: %s', [ExtractFilenameOnly(Cmd)]));
+ except
+ on E: EParserError do
begin
- DoLog('Error: %s(%d,%d): %s',[E.Filename, E.Row, E.Column, E.Message]);
- DoLog('Ignoring error, continuing with next unit (if any).');
+ eMsg:= Format('Parser error: %s (%d,%d): %s',[E.Filename, E.Row, E.Column, E.Message]);
+ If Options.StopOnParseError then Raise;
end;
- end;
+ on E: EFileNotFoundError do
+ begin
+ eMsg:= Format('Error: file not found - %s', [E.Message]);
+ If Options.StopOnParseError then Raise;
+ end;
+ on E: Exception do
+ begin
+ eMsg:= Format('Error: %s', [E.Message]);
+ If Options.StopOnParseError then Raise;
+ end;
+ end; // try except
+ finally
+ if eMsg <> '' then
+ begin
+ DoLog(eMsg);
+ If not Options.StopOnParseError then
+ DoLog('Ignoring error, continuing with next unit (if any).');
+ end;
+ end; // try finally
if Not ParseOnly then
begin
Engine.StartDocumenting;
diff --git a/avx512-0037785/utils/pas2js/dist/rtl.js b/avx512-0037785/utils/pas2js/dist/rtl.js
index 3333f8268e..1300ffd5bb 100644
--- a/avx512-0037785/utils/pas2js/dist/rtl.js
+++ b/avx512-0037785/utils/pas2js/dist/rtl.js
@@ -707,10 +707,9 @@ var rtl = {
},
intfAsIntfT: function (intf,intftype){
- if (intf){
- var i = rtl.getIntfG(intf.$o,intftype.$guid);
- if (i!==null) return i;
- }
+ if (!intf) return null;
+ var i = rtl.getIntfG(intf.$o,intftype.$guid);
+ if (i) return i;
rtl.raiseEInvalidCast();
},
@@ -739,15 +738,20 @@ var rtl = {
delete this[id];
old._Release(); // may fail
}
- this[id]=intf;
+ if(intf) {
+ this[id]=intf;
+ }
return intf;
},
free: function(){
//console.log('rtl.intfRefs.free...');
for (var id in this){
if (this.hasOwnProperty(id)){
- //console.log('rtl.intfRefs.free: id='+id+' '+this[id].$name+' $o='+this[id].$o.$classname);
- this[id]._Release();
+ var intf = this[id];
+ if (intf){
+ //console.log('rtl.intfRefs.free: id='+id+' '+intf.$name+' $o='+intf.$o.$classname);
+ intf._Release();
+ }
}
}
}