From 2f54c7de00cb145a9211512b63b15028d61d8228 Mon Sep 17 00:00:00 2001 From: maxcodehack Date: Tue, 13 Oct 2020 07:58:51 +0000 Subject: [PATCH] Update oberon07 from akron1's github git-svn-id: svn://kolibrios.org@8097 a494cfbc-eb01-0410-851d-a64ba20cac60 --- programs/develop/oberon07/Compiler | Bin 306680 -> 305096 bytes programs/develop/oberon07/Compiler.exe | Bin 308736 -> 307200 bytes programs/develop/oberon07/Compiler.kex | Bin 268189 -> 270605 bytes programs/develop/oberon07/GitHub.url | 2 - .../develop/oberon07/Lib/KolibriOS/API.ob07 | 17 +- .../oberon07/Lib/KolibriOS/ColorDlg.ob07 | 6 +- .../develop/oberon07/Lib/KolibriOS/HOST.ob07 | 92 +- .../develop/oberon07/Lib/KolibriOS/Math.ob07 | 92 +- .../oberon07/Lib/KolibriOS/OpenDlg.ob07 | 8 +- .../develop/oberon07/Lib/KolibriOS/RTL.ob07 | 49 +- .../oberon07/Lib/KolibriOS/libimg.ob07 | 4 +- .../develop/oberon07/Lib/Linux32/API.ob07 | 86 +- .../develop/oberon07/Lib/Linux32/Args.ob07 | 70 + .../develop/oberon07/Lib/Linux32/File.ob07 | 132 ++ .../develop/oberon07/Lib/Linux32/HOST.ob07 | 102 +- programs/develop/oberon07/Lib/Linux32/In.ob07 | 85 ++ .../develop/oberon07/Lib/Linux32/LINAPI.ob07 | 89 +- .../develop/oberon07/Lib/Linux32/Math.ob07 | 92 +- .../develop/oberon07/Lib/Linux32/Out.ob07 | 284 +--- .../develop/oberon07/Lib/Linux32/RTL.ob07 | 49 +- .../develop/oberon07/Lib/Linux64/API.ob07 | 86 +- .../develop/oberon07/Lib/Linux64/Args.ob07 | 70 + .../develop/oberon07/Lib/Linux64/File.ob07 | 132 ++ .../develop/oberon07/Lib/Linux64/HOST.ob07 | 106 +- programs/develop/oberon07/Lib/Linux64/In.ob07 | 85 ++ .../develop/oberon07/Lib/Linux64/LINAPI.ob07 | 89 +- .../develop/oberon07/Lib/Linux64/Math.ob07 | 447 ++++-- .../develop/oberon07/Lib/Linux64/Out.ob07 | 299 +--- .../develop/oberon07/Lib/Linux64/RTL.ob07 | 49 +- .../develop/oberon07/Lib/MSP430/MSP430.ob07 | 125 ++ programs/develop/oberon07/Lib/Math/CMath.ob07 | 462 ++++++ .../develop/oberon07/Lib/Math/MathBits.ob07 | 33 + .../develop/oberon07/Lib/Math/MathRound.ob07 | 99 ++ .../develop/oberon07/Lib/Math/MathStat.ob07 | 238 +++ programs/develop/oberon07/Lib/Math/Rand.ob07 | 81 + .../develop/oberon07/Lib/Math/RandExt.ob07 | 298 ++++ programs/develop/oberon07/Lib/RVM32I/FPU.ob07 | 465 ++++++ .../develop/oberon07/Lib/RVM32I/HOST.ob07 | 176 +++ programs/develop/oberon07/Lib/RVM32I/Out.ob07 | 273 ++++ programs/develop/oberon07/Lib/RVM32I/RTL.ob07 | 390 +++++ .../develop/oberon07/Lib/RVM32I/Trap.ob07 | 128 ++ .../develop/oberon07/Lib/STM32CM3/FPU.ob07 | 465 ++++++ .../develop/oberon07/Lib/STM32CM3/RTL.ob07 | 388 +++++ .../develop/oberon07/Lib/Windows32/API.ob07 | 20 +- .../develop/oberon07/Lib/Windows32/Args.ob07 | 4 +- .../oberon07/Lib/Windows32/Console.ob07 | 4 +- .../oberon07/Lib/Windows32/DateTime.ob07 | 27 +- .../develop/oberon07/Lib/Windows32/File.ob07 | 37 +- .../develop/oberon07/Lib/Windows32/HOST.ob07 | 84 +- .../develop/oberon07/Lib/Windows32/In.ob07 | 309 +--- .../develop/oberon07/Lib/Windows32/Math.ob07 | 92 +- .../develop/oberon07/Lib/Windows32/Out.ob07 | 281 +--- .../develop/oberon07/Lib/Windows32/RTL.ob07 | 49 +- .../oberon07/Lib/Windows32/UnixTime.ob07 | 64 - .../develop/oberon07/Lib/Windows32/Utils.ob07 | 76 - .../oberon07/Lib/Windows32/WINAPI.ob07 | 167 +-- .../develop/oberon07/Lib/Windows64/API.ob07 | 20 +- .../develop/oberon07/Lib/Windows64/Args.ob07 | 101 ++ .../oberon07/Lib/Windows64/Console.ob07 | 4 +- .../oberon07/Lib/Windows64/DateTime.ob07 | 27 +- .../develop/oberon07/Lib/Windows64/File.ob07 | 139 ++ .../develop/oberon07/Lib/Windows64/HOST.ob07 | 88 +- .../develop/oberon07/Lib/Windows64/In.ob07 | 307 +--- .../develop/oberon07/Lib/Windows64/Math.ob07 | 447 ++++-- .../develop/oberon07/Lib/Windows64/Out.ob07 | 310 +--- .../develop/oberon07/Lib/Windows64/RTL.ob07 | 49 +- .../oberon07/Lib/Windows64/UnixTime.ob07 | 64 - .../oberon07/Lib/Windows64/WINAPI.ob07 | 152 +- .../Samples/{ => KolibriOS}/Dialogs.ob07 | 0 .../oberon07/Samples/{ => KolibriOS}/HW.ob07 | 0 .../Samples/{ => KolibriOS}/HW_con.ob07 | 0 .../develop/oberon07/Samples/Linux/HW.ob07 | 52 + .../Samples/Linux/X11/animation/_unix.ob07 | 74 + .../Linux/X11/animation/animation.ob07 | 89 ++ .../Samples/Linux/X11/animation/gr.ob07 | 292 ++++ .../Samples/Linux/X11/animation/out.ob07 | 142 ++ .../Samples/Linux/X11/animation/unix.ob07 | 74 + .../Samples/Linux/X11/filler/_unix.ob07 | 74 + .../Samples/Linux/X11/filler/filler.ob07 | 221 +++ .../Samples/Linux/X11/filler/filler.txt | 15 + .../oberon07/Samples/Linux/X11/filler/gr.ob07 | 292 ++++ .../Samples/Linux/X11/filler/out.ob07 | 142 ++ .../Samples/Linux/X11/filler/unix.ob07 | 74 + .../oberon07/Samples/MSP430/Blink.ob07 | 43 + .../oberon07/Samples/MSP430/Button.ob07 | 103 ++ .../oberon07/Samples/MSP430/Flash.ob07 | 157 ++ .../oberon07/Samples/MSP430/Restart.ob07 | 106 ++ .../oberon07/Samples/MSP430/TimerA.ob07 | 118 ++ .../oberon07/Samples/MSP430/TwoTimers.ob07 | 143 ++ .../oberon07/Samples/STM32CM3/Blink.ob07 | 57 + .../oberon07/Samples/STM32CM3/Button.ob07 | 114 ++ .../oberon07/Samples/STM32CM3/LCD.ob07 | 366 +++++ .../oberon07/Samples/STM32CM3/SysTick.ob07 | 79 + .../oberon07/Samples/STM32CM3/TIM67.ob07 | 143 ++ .../Samples/Windows/Console/Doors.ob07 | 58 + .../Samples/Windows/Console/HeapSort.ob07 | 101 ++ .../Samples/Windows/Console/Hello.ob07 | 13 + .../Samples/Windows/Console/HelloRus.ob07 | 26 + .../Samples/Windows/Console/MagicSquares.ob07 | 48 + .../Windows/Console/MultiplicationTables.ob07 | 52 + .../Windows/Console/SierpinskiCarpet.ob07 | 75 + .../Windows/Console/SierpinskiTriangle.ob07 | 44 + .../Samples/Windows/Console/Sieve.ob07 | 51 + .../Samples/Windows/Console/SpiralMatrix.ob07 | 56 + .../Samples/Windows/Console/TempConv.ob07 | 44 + .../oberon07/Samples/Windows/Console/exp.ob07 | 117 ++ .../Samples/Windows/Console/fact.ob07 | 59 + .../Samples/Windows/Console/hailst.ob07 | 117 ++ .../Samples/Windows/Console/postfix.ob07 | 123 ++ .../Samples/Windows/Console/sequence012.ob07 | 79 + programs/develop/oberon07/Source/AMD64.ob07 | 363 +++-- programs/develop/oberon07/Source/ARITH.ob07 | 63 +- programs/develop/oberon07/Source/BIN.ob07 | 47 +- .../develop/oberon07/Source/CHUNKLISTS.ob07 | 4 +- .../develop/oberon07/Source/Compiler.ob07 | 23 +- programs/develop/oberon07/Source/ELF.ob07 | 300 ++-- programs/develop/oberon07/Source/ERRORS.ob07 | 5 +- programs/develop/oberon07/Source/FILES.ob07 | 7 +- programs/develop/oberon07/Source/HEX.ob07 | 108 +- programs/develop/oberon07/Source/IL.ob07 | 289 ++-- programs/develop/oberon07/Source/KOS.ob07 | 113 +- programs/develop/oberon07/Source/LISTS.ob07 | 26 +- programs/develop/oberon07/Source/MSCOFF.ob07 | 117 +- programs/develop/oberon07/Source/MSP430.ob07 | 63 +- programs/develop/oberon07/Source/PARS.ob07 | 257 ++-- programs/develop/oberon07/Source/PE32.ob07 | 525 +++---- programs/develop/oberon07/Source/PROG.ob07 | 460 +++--- programs/develop/oberon07/Source/REG.ob07 | 15 +- programs/develop/oberon07/Source/RVM32I.ob07 | 1302 +++++++++++++++++ programs/develop/oberon07/Source/SCAN.ob07 | 330 +++-- .../develop/oberon07/Source/STATEMENTS.ob07 | 947 ++++++------ programs/develop/oberon07/Source/STRINGS.ob07 | 108 +- programs/develop/oberon07/Source/TARGETS.ob07 | 73 +- programs/develop/oberon07/Source/TEXTDRV.ob07 | 16 +- programs/develop/oberon07/Source/THUMB.ob07 | 59 +- programs/develop/oberon07/Source/UTILS.ob07 | 87 +- programs/develop/oberon07/Source/WRITER.ob07 | 42 +- programs/develop/oberon07/Source/X86.ob07 | 382 +++-- programs/develop/oberon07/doc/CC.txt | 36 + .../develop/oberon07/{Docs => doc}/KOSLib.txt | 0 programs/develop/oberon07/doc/MSP430.txt | 520 +++++++ .../Oberon07.Report_2016_05_03.pdf | Bin programs/develop/oberon07/doc/STM32.txt | 404 +++++ .../develop/oberon07/{Docs => doc}/WinLib.txt | 0 .../develop/oberon07/{Docs => doc}/x86.txt | 67 +- .../develop/oberon07/{Docs => doc}/x86_64.txt | 71 +- programs/develop/oberon07/tools/RVM32I.ob07 | 575 ++++++++ 147 files changed, 15779 insertions(+), 5223 deletions(-) delete mode 100644 programs/develop/oberon07/GitHub.url create mode 100644 programs/develop/oberon07/Lib/Linux32/Args.ob07 create mode 100644 programs/develop/oberon07/Lib/Linux32/File.ob07 create mode 100644 programs/develop/oberon07/Lib/Linux32/In.ob07 create mode 100644 programs/develop/oberon07/Lib/Linux64/Args.ob07 create mode 100644 programs/develop/oberon07/Lib/Linux64/File.ob07 create mode 100644 programs/develop/oberon07/Lib/Linux64/In.ob07 create mode 100644 programs/develop/oberon07/Lib/MSP430/MSP430.ob07 create mode 100644 programs/develop/oberon07/Lib/Math/CMath.ob07 create mode 100644 programs/develop/oberon07/Lib/Math/MathBits.ob07 create mode 100644 programs/develop/oberon07/Lib/Math/MathRound.ob07 create mode 100644 programs/develop/oberon07/Lib/Math/MathStat.ob07 create mode 100644 programs/develop/oberon07/Lib/Math/Rand.ob07 create mode 100644 programs/develop/oberon07/Lib/Math/RandExt.ob07 create mode 100644 programs/develop/oberon07/Lib/RVM32I/FPU.ob07 create mode 100644 programs/develop/oberon07/Lib/RVM32I/HOST.ob07 create mode 100644 programs/develop/oberon07/Lib/RVM32I/Out.ob07 create mode 100644 programs/develop/oberon07/Lib/RVM32I/RTL.ob07 create mode 100644 programs/develop/oberon07/Lib/RVM32I/Trap.ob07 create mode 100644 programs/develop/oberon07/Lib/STM32CM3/FPU.ob07 create mode 100644 programs/develop/oberon07/Lib/STM32CM3/RTL.ob07 delete mode 100644 programs/develop/oberon07/Lib/Windows32/UnixTime.ob07 delete mode 100644 programs/develop/oberon07/Lib/Windows32/Utils.ob07 create mode 100644 programs/develop/oberon07/Lib/Windows64/Args.ob07 create mode 100644 programs/develop/oberon07/Lib/Windows64/File.ob07 delete mode 100644 programs/develop/oberon07/Lib/Windows64/UnixTime.ob07 rename programs/develop/oberon07/Samples/{ => KolibriOS}/Dialogs.ob07 (100%) rename programs/develop/oberon07/Samples/{ => KolibriOS}/HW.ob07 (100%) rename programs/develop/oberon07/Samples/{ => KolibriOS}/HW_con.ob07 (100%) create mode 100644 programs/develop/oberon07/Samples/Linux/HW.ob07 create mode 100644 programs/develop/oberon07/Samples/Linux/X11/animation/_unix.ob07 create mode 100644 programs/develop/oberon07/Samples/Linux/X11/animation/animation.ob07 create mode 100644 programs/develop/oberon07/Samples/Linux/X11/animation/gr.ob07 create mode 100644 programs/develop/oberon07/Samples/Linux/X11/animation/out.ob07 create mode 100644 programs/develop/oberon07/Samples/Linux/X11/animation/unix.ob07 create mode 100644 programs/develop/oberon07/Samples/Linux/X11/filler/_unix.ob07 create mode 100644 programs/develop/oberon07/Samples/Linux/X11/filler/filler.ob07 create mode 100644 programs/develop/oberon07/Samples/Linux/X11/filler/filler.txt create mode 100644 programs/develop/oberon07/Samples/Linux/X11/filler/gr.ob07 create mode 100644 programs/develop/oberon07/Samples/Linux/X11/filler/out.ob07 create mode 100644 programs/develop/oberon07/Samples/Linux/X11/filler/unix.ob07 create mode 100644 programs/develop/oberon07/Samples/MSP430/Blink.ob07 create mode 100644 programs/develop/oberon07/Samples/MSP430/Button.ob07 create mode 100644 programs/develop/oberon07/Samples/MSP430/Flash.ob07 create mode 100644 programs/develop/oberon07/Samples/MSP430/Restart.ob07 create mode 100644 programs/develop/oberon07/Samples/MSP430/TimerA.ob07 create mode 100644 programs/develop/oberon07/Samples/MSP430/TwoTimers.ob07 create mode 100644 programs/develop/oberon07/Samples/STM32CM3/Blink.ob07 create mode 100644 programs/develop/oberon07/Samples/STM32CM3/Button.ob07 create mode 100644 programs/develop/oberon07/Samples/STM32CM3/LCD.ob07 create mode 100644 programs/develop/oberon07/Samples/STM32CM3/SysTick.ob07 create mode 100644 programs/develop/oberon07/Samples/STM32CM3/TIM67.ob07 create mode 100644 programs/develop/oberon07/Samples/Windows/Console/Doors.ob07 create mode 100644 programs/develop/oberon07/Samples/Windows/Console/HeapSort.ob07 create mode 100644 programs/develop/oberon07/Samples/Windows/Console/Hello.ob07 create mode 100644 programs/develop/oberon07/Samples/Windows/Console/HelloRus.ob07 create mode 100644 programs/develop/oberon07/Samples/Windows/Console/MagicSquares.ob07 create mode 100644 programs/develop/oberon07/Samples/Windows/Console/MultiplicationTables.ob07 create mode 100644 programs/develop/oberon07/Samples/Windows/Console/SierpinskiCarpet.ob07 create mode 100644 programs/develop/oberon07/Samples/Windows/Console/SierpinskiTriangle.ob07 create mode 100644 programs/develop/oberon07/Samples/Windows/Console/Sieve.ob07 create mode 100644 programs/develop/oberon07/Samples/Windows/Console/SpiralMatrix.ob07 create mode 100644 programs/develop/oberon07/Samples/Windows/Console/TempConv.ob07 create mode 100644 programs/develop/oberon07/Samples/Windows/Console/exp.ob07 create mode 100644 programs/develop/oberon07/Samples/Windows/Console/fact.ob07 create mode 100644 programs/develop/oberon07/Samples/Windows/Console/hailst.ob07 create mode 100644 programs/develop/oberon07/Samples/Windows/Console/postfix.ob07 create mode 100644 programs/develop/oberon07/Samples/Windows/Console/sequence012.ob07 create mode 100644 programs/develop/oberon07/Source/RVM32I.ob07 create mode 100644 programs/develop/oberon07/doc/CC.txt rename programs/develop/oberon07/{Docs => doc}/KOSLib.txt (100%) create mode 100644 programs/develop/oberon07/doc/MSP430.txt rename programs/develop/oberon07/{Docs => doc}/Oberon07.Report_2016_05_03.pdf (100%) create mode 100644 programs/develop/oberon07/doc/STM32.txt rename programs/develop/oberon07/{Docs => doc}/WinLib.txt (100%) rename programs/develop/oberon07/{Docs => doc}/x86.txt (86%) rename programs/develop/oberon07/{Docs => doc}/x86_64.txt (86%) create mode 100644 programs/develop/oberon07/tools/RVM32I.ob07 diff --git a/programs/develop/oberon07/Compiler b/programs/develop/oberon07/Compiler index 972db287b9855b3a78eeb1d4f86c06a591fdbf7d..b3bd70e60a8e1dc8025577757a02bd3795d68f8a 100644 GIT binary patch literal 305096 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

iL*YZ6tRCf5y4gDMGzl&sLA^hLS`zBm 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

0P7q_;b7Eu#5V)aaY-Y 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

je%<7C|$R^88@y}7Po$1 z*`c+yvSaI4l_jm8RhG7XT-mAh{mRa*ODemxzFE0i>uZ%|tuI%0ZC$8JjYLJ7uop*{oF+Y5X&%sTSnhG6HUI)b-YstSc8sdgcpD3y`cR;bf1gvu?XHR(Mj?2dFK*;C+BxJ2^n3xkZlI;`{+9ys# z+J>yH_C-_BKK$ zSnF9P*wHz`?twMpyg@?y#G?rf%NOi33AP*9m@lgP&J)#~`6~6g+5p&%R>;h^g+e*= z3ExZHpAhw_NxZ3It={ackV(A!cS0udPYRhUgxR={37Hn_ON;1eqpT}jVEWo zA2f1BZEx|3s;`~Ir&lc;*Hp-a)z!R-^|h(2qe9j!{QjF{L(-Y590nW20faswJ~34I zOB7l3Mf{vBceu%BB%ru zDYhtxQBWf)&T^JmIYiC(Jnzij?j-^LAO5_|&b)oznR#b+c1BXv?lh)EyFQYlc3qhg z?T!~XTBa#eqFn=~M7t_P$ePC=ObL$&Q=&2N)(zI9c03th=e^IAX#5saK2m;-sU*Y$ z>LsSWr^Zh+CBE@6QsNt5-vZx=HAcQyhc~>(Oa%5wwx{nnt}T~SX8=`PTO8wdJi)ca z9d00bagx)Ssz;ObWvV_+(v7JWtC4EUlyuU~m`dURnZlF|l?hCVs(=2Dl&JaxQ-|p4 z`n}Nqa@F*r|eY2P#5N86p*ADAR z6KMh|!gnf~nGOo((*(DH224C`_4z|Lgv;B zHop+*>jic(Ql~LDS)1?z<~Cxh?#x_lmJ2>cdXnF3G*XQvKRAo@+UxXuO3|E{0ulKY zsV1cSHB*OAL+Vqe>YR?$`$(Z5pG6!gPiTsixo)@E_s>mY9bVw)ItZc#y872Bt16Kq z%=T$U$JtlVI-^0^?Z*qr$2h~CsFAW-ygZkMAdW7?9NoOrU=vu2LBiW2D9zW0f|>E|gW3NKvt`EBq#Aj4d?A*`Ogqg0zgOctR_YUSJ~mNTfZ4 zDUoad%l{2F8wx2$NI6}s15?rv(vU(0j2E7!0^VXxITi2$d47y#0JvxSQNZ1gwAOGh zQld=-nclwEtz*55urlf)QLke=tz;?8li+xRj9Sy&t9F;%28YU4}>hLe*iiR1$M(Ovya; zc0wiu4^m$#Z^;IG1zWJ+W|6Dg5>R#0Rwi<3PWqQNRblvR~TQL%3W zm2|9fh_ZkFllC=qBKKnYtvZnUv6QU>CD>AZ3~kM8dqcRUjcLVn6P@1c$uC11{GtE2iy%(2Zl$|cPux6hCq_~FI;zt9R5_|Mw zO4?|rSY9in#75&OSAJ;*trDx>`*i&d70yyr?0bO5bZo>+YVB8k6dRdfOyS9?UtZg* zIj&+V`y5ENoGJ0<$C#2S$0DYhu}0@IB{iDIl!TR&nGy{qA|=wUx_tBH86qVyB{S~7en6@o<*t+zYj{6W zsCmI>xr6@`(+R=+g@D;d=!R^m>zK+q8>ttW5*s|FA@8N;atL$c*prnNw6?fN@=T8 znUZ#p&Qu~b?;@q7*M=#kIgInP9V7XHJ3maEzZ~7)_ zWFo&1M$dJU!0f==1H#N^vwBTn_9bx(9$w#I>~j`^Gv|Rk;=gN1*TIoHq6@3zBxcUx ziA=}3dzrGE=q&H)CwzhZGN_@ulJQ#DB}RH_$i}$pq1bn?E-y(ym!Qj$nZry24e^o_ zjP`zNKLXnqM$8-8ZN!{XSm9;Su#Ps#=^{EFwxQ%%Q-XDPr1&xf>Vx_3ws5Z^dR~s?fJ7T1Y zU$_Pys}?^PZ{QU9RL92sz>W->){_pcPmYUI2_q`n0DK!8Ow8sy9EIbp1YR;?d~i-F z!D74lvUEwm z;g;qUTYDLf>@O_EfnayYhJ?DP zi+rt8B2M^d$IMh@;#hmW8b3dG1U8f0OUJ_9w2{k@nS_hc8;9zs94B)aGLv&U<#s^k z3@0-knN>L!AnVGzAVF^(!dPh_=)Y);2~=;6z8M^Mro~!>cJGRf7C7UL6z*7tkoJ{W z6sMcvlkpE3O-sqQEE%dx{3w}34pQ zZ;Axzp?C!^nna~FW$gYO7P3vFd$iOkJBB&=SjNOQZheC@FtFXM88N09484aPUh?ZW z-qSZOZREVx!}AZbA~4=HC+K*9VmxG3;L*vw61jtCbELqB`8aT+`O6*xRd2a8T98JY z>NF&`m7zhM3KHr#RS@DJbIrJhy3f2DFSpcB7yn~!B-bx#hdQP8&p?4QzHQx94=$v4 zVGN6+-;;WlivlY_^5-jHPS{SYa0qw>-V9|l3=|0$OAL3g#yBSL4j_-L1!|&N_vp>f^Nkb3l0}1pq z>PWu_zWEBH^t-42gB{v{#_li=I5!U4r2yx|C7p_#5D#z$0hSVg`;Sm#h&r=)^LQn` z>`RE;hL1@r>qJ75aa~YEECe(*osJ5A-4<3j=P~X)CFMfNoW;z(PNr3OCPbBjt}Hmt zDad|7GS6&>%%oW6y^%*;RfkcuB#NeY=!(%(0ITamihsd!v}1JpZnR3&+Q7>_wU$XD z8v*6i+V)2s0#a1sArPyz3xULkfL5`&M#&nCfn0%(=$#*q%1dEsC&-C2d6aGMoSa->ZP&+`^>~ zAx4EF1j`-b<+t?_#{whC??q4$6N==L6-Jg01hAWg?IMxR;MNT7V}~>l_l8N$Op1|} z;)@-!Xb$!htQlO#&Mm1{;R4NpsTRNSc(s1 zihb8!>Z#SsDS(YtXovZ44?8+Z(dQ^~+#*)1tuchUI*cQUX8`AEZI>`wU(1*^wx@4A z!Ey;^8jw}!N0tk4H36<902&Z>sleiX^q)mo5y8hW^H|qghm|E@VrI|g1Im%k`81bj zs+AEoatAZJArmKpO6Cd3ypown;M#Zw0A&P-3}@!a$n2MUvSec3CCADnAd$1r&;)>7 zM9sFGgNvvI5@~Ei6KUV(sy4qT0Wmgr9voC2kQ_wg0ksKz5NyxPV0s2BqlBH3fia!c zB&t0Dgy@%x(JiAgai1js?Wd?_%z$?g@Js_Z5rD1(OHoG@)#AVq4L;)@^OAKeNLE1N zD$t7?owCT_Gb}?_lQ5h4TbPfE0n>`%`TO{Bu>=}lqFb@)Xj;n>j?z2W)x>LgCu!t^ z26|id60JZj`F_%t&*9>s?;`YQ1Dyk)$i$$y8S~s8vpFJW=`pRsMQG4&ule_qSixkc zKzhw@oPz9Px7Yl@$+QalL%_%)*XA=Q$PO%2dwb3@!0Vn zFZ>anU}(&bFXaBIJHXu;??Fsm1)Z6HvHVR{j4=7kiJ1czV)e>I@M85NHjuzV4D`%w zXbr9O6qdN1kr?}~FYhTVp`FqD%t02s_rE7{fio+ zO<+RzDfY>DL+WB*ozZgNajID{c%59^5`UAd7*wUJIjAbCyaNlYP$3PqIHO01yXn%z zAJ@RWV7LIRItDgmKEkVWq08{@h~gb^sB*pZa4(rf%_+Jr!T}_Pb!AXD4%6 zlD`=~MD-jOf>gJ~qig_*W(7BxCzD7{-z2W?mNPcDt$e%I!79QlEA-T1b_QEF`S8c) zDF=wkyXQ>Ly-U6$>X?(B+W@5)8WJM6qo@lqUX>z$&Lz2HQG}i)A;LqMyXKseJ4}k& z=bVuH2#S(ebUKPUA;XfQwmBVg{h58XM>-?Bb58Tzrjp$b^MmJs0W-3<{+;G*!CE(y zQSZt`WE@ZvbDHIzgnA1m_)+_x0o2|FTn@8En~<==JSjr}FzTpv1XxV~OeC$Mr2_Gw z1A%cv@r8uVu?rA&a~?IsxxB|04v}fdPRa@828ATEuSa%_{w0JN3m9L{?%WgAczPq| zs8|6Aa@11;9AL8QDGyOKoa^k|x?Rs~-41fBQ;kR~C0LJR^05Gk>y(r)Mmi1M&nmc_ z={iQE>3|>G3)ev)ntBk^BV?%xEM3P@fk*kl7v~axM2$Il8-*ce86K=6Za2ay$M|I* zm=?@Sg;4K`%M*?#!Jvd1FQf-Y(EB0P@i4Pd?b?PE&o4HEIOyetjD^m#v-vvKxP9H4&}h zAWKV~iC+s9;sBs)iWaL!f|w|y>hRA&nExgyRkP9(5)a>pUoB4p&GIb7bD|w`&&kd` zi^cE)8gX_^dU?E)8jo|Wgk#myz=iwsIp1ctHiN!!DnP_2U2{9*H0(t6I=sSIZ5#lM z0OZhxBvXQeX^`Dmw8obre)|-yiv9|(zPembnmN?zUAJ% z6y-N0W1S9{Z)N54i}Up-Jc(sk$Hhc%u(fnE&WB2rYrRLFLB{sp?fQz#1p~ zGCqH)Xxrf~qy_R%9 zhkMdD{=hG$utA2Jsy`~j{t-E-%OdDw6`cqgR`|Ov0;C>e`TM$@5mwHpR(NVxfHTrk z{Sbk%mdk^A4A?SI6>5>hroOC^9ANV##KtNY);aE`aGS71;C`yL|IHC9poWOBX(OA#c(mw@&T7UoC46ztV_ zu);6km*ulH+naC$bl;Im{ zbrayR-dKW&4j+8u>L?AH2iWCE@-yp1#rsk)1n5b_47PqwGiGq1ataX9d{yKCP8?j_ zU38cSS*)T*@L+}S$FH2H%R$R3dK-bW6+Wg3;4~3<0%vsgtKW;<6)*uIvoF*x^$mks zeFQ^NRzKPDMx8k0Y=2%{=yKdfC(2n*dJ{lTwM0$hxZPCw1C*c6t!_#Bntd91~nI_#3HQ7c^LKV7g2Yx{&?KF zF15Ib&&9smYw+Gm@*DR<&LMPw$%J#xd0dQdAFS|dziTHQQ7Ykmjmx{PH1A;w5oL6^ zi74%!S_Irq`z3f-;ZE>u2yVKCkI45t@HNv9>60#G{4E`d6c0eL>65krlgt0;Yd$9C zF~rmd`zKk2XR|k9Rn8e!>H_jySX+H3fb5jkxkaC_=zSJ>KJ4B(&*3h`>rq^j`)*<` z)I_nq7;Wi}n%N^<1_CzG0W%j6#okF|cc=zA#DOe`9_JFw8Xdy>r*YClkwU8;U& z!bSa*ved7M8c-UZWe@G)z*cvQjId05vU_0p690u4Ff>NhF|l(GHHv zw?j4c7^n%R*86$RfJpl}($;$OphbITXXu?DT?O^6qMPu5Gc)n4C`|wj>KYfm72ruC z0TQ4~dL1El5LA*jswe<&s&M!ptp<->z_| zgoH{0sT_s?_DPxw#|_*%jRz~-0>7#!5p?aI4f7es+kgUV+|Fo_J43;LyI_9H-|$p) z(&`tO%3wAUOkp-(V-6tZMq=VN99%AzOtiijJhe-81+JKa~5`1)xNu`ZJXKH+GKPVVtiLL}? zNZP!A1;n-qv0plnSOmW+A)Z*WOYA|H*c$keVL{F84Zs93?0|sX?~~fggG0&;7PqdQ zhHA3HKV#?<9r3d~pn7OU;pC^08XRi5iKsIm#t9&+E&+%dO(S1M25h%xHk`p{S=|y^ zUrHog4q89&i=&l6S{0zL8j)6g(rThwPYc-uN_IBMa(|qCCou}5xSy*I zM!wwf8v8p0DyTp851O<+R)gSft|3U}W&>n7_M$QH{8GbtY{+3*fstxP>a8^@?z`gB zLGGP0nQxl&a_#}3FqFyapb2GZLe&1>uc^I^?@K`lE&3C`$apNK?nq(k&SzJMOKS*` z2O+Md5MdPA_Y=Gz+QKTDDd;))6|*(NrDT#5B7`XP1A|B-n(kthx>*a92ck_xAOKW= zpj_=$u0BH>hmh%{Q4qzkbZvxY3;ZGoRb8DfxQix}0Ww>Ww5#xn2M9P?ErJw6eLjm2 z6CeaF@dJAgFw+Bq?gNW}s@5?S-l*|$q}(oP|2JWbV^>qDuEo|1airBuXuOMnhdzh< zuk1pNiPHwp10yT^a%&wypAGHoAPe)OGRrTr(05wlE|@xsQFyKyPqjqNzlAv%J){z0 zkm?3`BD_4k-e5P*lgrZ;UtOdGud0h7Y~&YOt-h2#QOnTDD*6%czhH;%R(J-60le`q zh_=Ov%ba)@L_1pHzv>8gTD+}i-P^gRsH3~+odpqMu6dRg5OO=sdjTvz5*AT+qA23m zdK{KmTl%lUuf$pe>q0Q@kK>_LAK@>$xn&?_0=e6$&dj}(5T_EG$>r>sPADbCx1zXa zD0K%hGl{7Kxk1_7L}Q}7EEe`eAy(C^vX_ZjrIdsDr7qlL!qs(&oSEIrEu6x_{d

Me!c`Hc0?L2mV9A;oN4K?K_Zg$K@LA$B70zNuJIRu^=heu$%9 zfhUEMR4F63V&Ch8HXn#pC8K?nF_bQd;u6kY7$2>0^F*?wD-NIwK8+uHC1LWTr3nBi zsw3m}P?-i3>=;1MWA6q7v=W3e+rZYIs&U>HoU8GGQ|Fl_q&ayc&M1SEpcWBlC;zJVlJ>H3lwSe?a)$8{^Z|V9gdRj#%$fuxSKv?pa@j z2*L^vf)8j;Ux^as>LP=as2(8B*_z2^xGD&BV1=h(l(qZl%*%1=JW^J;C4TKT%*>B+ z6%4mdOMaEUyu=wm9t8_!^XFS(wj6>z1rLLBmaBJ|fY)+PooJ>AxS#cNI7q&U^QWT~ z*lS7CxlQIVJmA(+j6P5T!+k3fzb8ig9MaU?LS}d`b6F0kNyx;z9PBMQ{(2v)J|880Ezd@Qg}^Mz@5ua z3x%cll_=xFoM&=5#d19DBq2!u8cI4b`yxS6FN}$rTka9{crqFeR5g^`&ePm-bBe5R z65=JX3vTJ?F1$Ok)aAGdu`_BC96tuh8XTRAGH{@h;RwwF>Ul_~J_V}!n6dX~-~#b* zn&uXyutrC&jga$Oj(P=hk7d{wBkTD*YN$X(g&RX8m))z@Dke;z&*j%w8f9 zu4M|591_unKAym1G%(J#94s=NMj2AU0p~vUmYnW{ka~Mwf_0_RNvyh&e~L-e$}7=2 z@KfJ1o{zK;ZGX;rB6q%Uz&VnCHK*PeKvB(MxZ&^t8bS>Y&Owd=wQjf8S&TZC9A=Wk z9CFByJ||7_c0A}i2Q=xQ7#2?f7`va)zv@2FF!56}P_Rd6ykeN(ssj!ZI^}U6K#A}sk=#QcX)OMnm5xgK8w2Ce~h{5nWE!OE8 ziyFQ2iBuM`CIHJ`su6CqislKw!gziiYw)W8=85EYDfx}p=%JhqR`^_viXh@WF`tBs zV>Lfw9YoUZtr2i#;TULwwLcx8IQp&Dm>&JgfcXY6m5n01vZ?5Y8w~d%WrcV1*)>mA z4fIl=&mj5=qQ9)sZ_e3}+gtj-TXQONZ`DR>sc~tf$9IX5$a)Bc=KU+M>Md5$4Z?N2 z<_b;sAp~YCs8Tm;94gubILIWWi*+u|9YxYk*OVq<{v(uH#3(J%l!(+pBT@9Xh;$gQ zE5QCXtLR*@S-VtG8tgfT(d>VMOQ8{xeV8~~H4ZKtdkgag*coFxW;T0)0FP^?-uMbO zxe-tHql9$sBbR<|vaIX8o&da}DHw9CZ~|tC9y2%AY(2HK0DN15FS05?jJR^`<1&8R zA@2g0@rwxt(_fYu>nvAa07D%^A=0!E8--^g9<1w5)mZ<|DLb_?> zD%V`zAX1EvNwM!s(V3HUVX-{PVX+)xfet|CjakkGdt7t59KAq;lj7bBls)ad7q}g$ z_61-EI4B0tFZ;%U?#A&gdZGIcf_4I^+6Df2h44Q9*t_T!&NY|UOI-gdvh3HHUl7GL zmkp!n6FTt?MWuSO-%49~_HAo#`1fSd9f>t6l<GC@+fRZ~c}iZ0iwQ_%k-g*jOs%EjdhR64GCZG=-oVW^M~ zM+{$p2w5FwnB1FK`O%l)99B`2KiIhH#RA1e1WVLp7`T3s?gp-MQy=|o1~=RxWS>Cb zUHFmrTfC`{C@VZDys3|VbU*Sun|8)M>G;tzH2&WAAl4GT@{)@iXUV*A2A|!2wGG&S zmaH)0O7K;|Q&aTlTP$8V$?G9QvmzHh@l zU(DncpbtxC7-OgvUV`BP-BxF+iLM19y)MsboZBA#SRM5TLeIzuLn>!rZhz#~mDx|E zA9Bexr(K~#lc8&Ny#&Q;`|NM*)FB`m$z@woKG4SexOi|)og8YdeyN4#x&?;&n!&EAMq3$3D z(hs1J4?Wl3o^d_blaDz)*RdE~?GD>O>q{)YLLAE~+JTf6ew)uRgES}HUt3*+WH;0D zb_WZJxB((Y?qGNS!E{-foY7SSBx?X6h0F0&@eb+rDq*KyXho4hsFwKxgB=X$LPbS} z)FODtc)<@m>ImL}0^JCK?9N*7##YfWB6veSi!F;8USDr$e+p(4^aaLB-;q8Y;$Mg@ zjMn#vvrvAF(TQY~Kt``~e32b{%aO9ePsn)V%LAsn=cO(-6r>a7{dZWUzH3;DovS!K zNcCl4SM0k0SylKTs-u3)h(V;Gu&;TNwM)JAY5`1D7gp2X_kOSGro>_W-QD4mtjYii zLUt@GO})lw?iV`I5B&L_Kl`Y8-B3ey7-HBJ=$_CI&5?d+J07g?Tlj@D{R%i%>jNMw z@b417M8k7b!bL#>zmV{C)n5~ z5+graB9sRS(m?!%5>$|sxq0O$G)xfrMu$)8A3oN>@!@^Qv4zHe8TdJ`TH!*>MzlBN zlEuZOksdN%ZWXeH7yF*+mcqT%)N;-ilqafT61A4AJg`vffXGO1G5OG9+fi!2h>b$f ztUmUCAZ3LY;Wy+{=S!%f&M~rGtz~Pf76S*x0Tw5zNm9)9*HzT{8q&&-t`VKj6LQ0t zC0@K$%c6H5UI0f#%)r)DNuTVdF&7EuF@o7JhFNU1r~_{5GP;G{4TM@f4Q$yO=1Naf zrp|jC#P+~%A;u;l_BI}@@SFIR%jGuHp153YkS+Ff=9%Y#g?hm7d5F>7ue7P*gDXwM zcI8lXG5pr7ZuEoX+?2HYE&g4ut|8v~IJ}1ik8$ZZ7w=yriT9Y`c_;5|A{A^HdfG${ zvT;i)!_ZOCG{PYTw9cln|3KdkEsI6VFY$o&TV{!|FN3K-1b63^<^do80$bn`M)2t( zfKt~&0F<oS2t}I(WZl}iqgCm72`KN+CpLQa4eJ# zTjL;TT|nl#AW{vcfCyt2Tlt=|KXvo2}?jjgc-95z5t2&Z}|& zW*3k^esq@T6_nw2!C}Y;ryvzsaxcXviNi`lbx;i@0d)dSl+;tS685F}o2XTZYAQyn zR1NVLEwQ;8M6-3$@?~2^{5;nRr{EVZJ`l9gEi_WCXoPnNDKGa5qEoD*{g}As-Utbr z0*VT(gVX~31I1oK==T5vy(i<6N0IrDpCPPx$;qVH$Y9Pe`d)-^L=~Y#$UIFl7m`e& zCNtG4x(z8Sd=q}b_#r|j;!cOV2-%g8mlHBSI#cY#9bec8f{B~vSqd;+-M^x4IX_bY zb;0Gl==N0j5R6~O`lm0}Covv;0%8S1?4T%s?W)Gj?}!n5+9g&;i2cY6y$O0giLD2y z&8_e-#qHRSjZ|(X%=J#HMV&q5jL?teGP7orHH8>qejv|DPJe1YL+ z9=y^;8gSh;T#8B|+|S5_Mz}_24?)A9;8#|%B00C^?uQ(I0ZK-jJXnDqaxZ#0`Y0?f zdxBbWZeF6^fN#QH0T};Em<}5Rlhkm;G18vEAe(ch25K=vxkz)98IjBsmB-8k+?9pv zWpcXZ;?(m>bv@Xa+P&>k*6tOW0c-akB<0j|8_-<{-QR^iOQ3sc=u$v`Na&Q{U2p{Z z;x|Pivsh3cLxi2qEYBO|e%Co|PKu95v3a8$wMS6*V&CHS66&yzKVCl>b<`liR>*b#rAIb+=SbP`T5Hk8>wWmuN9c^?|T3WD2t$;OBq0>d2Tbc3>ARz zJF0%!fO4MJzfTn*53}@L9TBzVZ;pZ|KjJO+y@iab5KA>AD*M;NNL_>NPg-9P9-3DUEoL9z^{p}mcsQ_fP2Y>3pj9= z12>R`;5yd@>Iopvhe-HX9j+QmRTDG_D?J$?>JhjWoG%LVR6;pM=9Mr{+uSKCA4M?5 z_6`mCA$TQ@Me*Zf?_RY1xYuJZ+92<<0x<>h!#<8@(}2*RXcm3A%wSsyKc5wg%$#t|i6GAozYbyPyI@$L8$@L0SK94o1Zmq7lJ z4L*nXN4Pcyqjjb7As*2DA}g`-^C#vg_%z?rZvx)ih^JK4lk7l$6Hm}@V_Q=nZ^KVe z^GT{b-AlL4&GdGNh-D*fJe&^TNcd)3N5VCd`X42n1(7J>$jZnIU{^=2f{6^f(O}2Q z3?^V5^Pk?<5d~#1nfElrCBZFVyMopT# z{40^hM-=)z0emWsOE`>IxLNpmT%dHHIlX@7*3vxckIy$Gmi`rK8H{Ej7@o1rFnp=k{G%1S1 zJ#b@DIdzf za0kmFMj3J{5Mxe*P0+QKso&u*BZ|l1Rx^E`3BC*FBW#omoq$ma-nVR|Is;TQG3}UA z2e_DfvNQ0)eM~74_{9s5_~=4_qYI%)u7eO|sKj*w+&mT3fu1pjrh!;S>F(^e{1;dJi2ZY1m+t38*dsP&G2F5IRbzKJ31FeJ@eN0Qc1kx_S<1&81gRTQd0Nu-Kzy4LRFY+XWT!3h4 z0Zh6?<)e3^hA5~9d7Oe}D#!wS_t;82PKTKfkW^cc!v3m<+rf*wjdMmrDY8&xM#I@4 zIvZHltXp9h^MGCR50b>5SI9KOuc=DbHl4+fL`4jZ4Ft{`?G>gp5+KQQLMnQ= z)E_4B^f>C06+#w2i(W#d_`$+lbbj{zY&KZ7%2|qC z=jEYxtlTS@3Ly@88RzR~&MBM z&^Isg5NJDn1WJP>&0$?WbR!Pj{`;jt9{BZmEuPD^LvfSpuzdSZjr{rK1!FMXF@fX?0 zO14k6mF!COh|W%s>?Bp6kMltLrqb(RoJxHDh&An9w9TMZkOSjX?~!!H>oneb2g$Uq zs+31l$r;ILhckHJ$ybM1+(4DwMdnh>3hb(pcSxzF?n5bNL~EtO`|Gkdq|B!#OBwu( zg~m;s?w)JH$r^m2fY(()JR*V^p>z9)bPZG=VLxm+c|R{{Uy2m@R0}*ZAYG)hqkmH1 zBvmzy0>i!-`iw1j=m2c-Ic;&$%i0zlN6;3RXxvi4t*gG}Bfm=ZV}i2p5i98u-ROF^$14|4&$cy!r@Cikix5qnU7!Z~jJ09ncOeGh3h> z;zYQq7KBAdLpZe-gqx0rfVr7;;`l5wRTbjF%l-%U;??Bsd^BnsYC-tB#Ss)VmWGL) zEu7?aieno*;HI8w_8=KbGSW~Z$qa!1ml`=b&0ITzHV;n|nzR3lCM~m%2-Pgn^GJ#j z;pJKo>KqM$H`tIv7q9*)!TA_HY+Rfr;zF$kwRp*}+EEu0HPJ;)t_2l+u3P=LRjYpV zfVGLlx3czgEYmyH>(@eeRqd!x5cL)pHN~K^t~(ijKs{&p|Eo^ojr1(Zwsgrl_gi^= zxvSPRt9Lx=N}}$?3;@a?oNhk0*%7>zmHLfw?`kyo{=#13(r9%w8WX)1$22q6;GE+Q z`NlQK%|!MvlFTnn?FMVi%S*+2GDZkLXJ|OwLcrc2SX&PmpaI5CR6xxP1s~iKv0!s5 zkUbyotFpgjy!4|u4MPoe)J~wk@0TSY70`7FsXidP=l`Oy*hxzN)w!u-Fxd` zGUL-nlvLtSkjy?G^Hc#j^m1J4h=JwSBc;xKyC-DfiJs8?-H`)#Vm0L}vX36(6to&l7ak8^LHKPR_=0Gz`)x@!y`dI_2RsPo%Y#Q_LisYQHe(`IwaFezf0%=5 zW9;NiZS`KPRWS{hKkZXMO^nL%QL;JlwL3_*?#S|v)Mx;o#UrhB-Ha46)#~QE3!J+7 zjbuNKdh15A)**{^gLn&7qo%Ma)K)JT#BqKQ4@woAunupU1mfuBu?UG!9It{&%6b)* z>ME^uWAE-A33prALzHSJ>rCFv`{Fesy~hN9^<#6@l*ed8K3ucLh;&HF0I1hS|*48sfK@HAH(4iRwJFE zfRz}l;t+yA@hK;eS_A)LU!qT#i0qtQK86E3TPaXiNZ6JiN{ zlA+t$*?m(B_L1V6vr4p$#ihN2#)$Krj_G8o#$)kh&~UmQX?3TtNN%2)mzT`(5AQUx z2gA1J9ZElzAN-BHVjWoC?`So#lg$L;6F}e%1u0;hME4vcFn|PJApyexYq}A(1k(g( z;TYb4dIu!YCsrcAQo1(h@F}gVUq&}{QL|PbLD{R$b(GB{L*7DDQ(3yL-9yVFgMBq+ z9;>k+qsJ_@dJO=a)ER9RAH~41w4K z2-JKn#u!5aJlViwj2iW;R^k3ej)w4QzJy^=iBFvoH)Z?T>zz^;qZ8)5F9=xd_#~$l z6q5Y^Yk2CxiI5(R^wCf3aMjd-x{sVS3;fBqxz5O@@lCfRXFvW>iJ${(?VBN@xVb5u zOl9RrY6QcS2*(_W{sQmE3*@<2@mFtii5^aYS3jXa>SatZLg?-N>ijxXvr@f-a=Q?F zd)UMmYUR9xWDaTKsyoMXjygzMv-WET;R$_9lATU8yN~upi5Sdj(=r+!!Y0T-C{0!T z1KsL}TB?^Q4d*OggrPM?(M9=jqo{NCYL=&!KPIGGsX~%Yzz$rjS3)58f459)eTC1u zuha=TyQ`&qHv%KE?N^3ctDQg!HKduka!v*_5dyEEk5i2);TTwf_IjCi!B9fJRQZki zj>?`v^GM47ovW4q=5M3?D)6xX!oCcW&i*-`^pO7#>Boii^=h^zeVw|Pq?a1fa?qkj z>Z*FRNS*1efwuA>RrU)=XBPaB{Ht|LQYUq1lh`@7^Q3l--T@Uz!HLb><40w9XOY)V zkJiTVNOsyagLZ1AHXIf^9jE4^cI=NibR0Qe;+;lbjwjW|(WBO_WD?|N1vMIcY<|H& z$z^!<*ec?y#a8^NyT)KRXsFXAa%+d(=SOdpE?LJS%hT`Qh~d(RQ1%x@s5Fu5*lMZ- zYZIZr#}?VG9eD!kf$1^5?gCM~G2lvrItPwnhjrW>i~mlN9x00(hfN=|mXhD}1H{y; z2Mw|tppmA~tNbq1IzkNt6yBEvxzkalQvP&99=K)}#6>#0jZ3bvrTYIXJy+cn zG4j)_Esv465Q;a?#Ekqr-g?;YBAb4?=qK&(o(OvzF?jO~E044Eqea+R*tLO<_+rwW zVrV9@rfSC2J4kn|p?l<*TEKd1Fovzq)v2ZBcw%aS$9WnQSBI@#;P}SB_3UFfj`G9_qRuq z`&}(JUz||RA`$)0dT<9b4XiB)*Q-0?PtpNzxf3l~tvUF2Y%xl&uQ;uTU-R3qDzT%V zagK4tWDamhS84~g3AR9kRksELgs3V^*WJMY;6ydf0peVtaWV{PLoULi!ERAyWD$l< z()p-6=y+!nvUVn`KU`EWi(_2wuoE?Y`fyx?;uOeTZ0dVa2Rt`rR_)*l45~M_YJ}G2 zKp!TV^%`1h<*pSi)Oa~5!M_Q$08qFfB~CPB$yBYboXvW(CYFw@tTWYh2!z?|Y|nsF z@?w(arFnANKv~vmOEl4dY6d{nk6|-6knE9|hNTOLDB)O|nx)fxwaFKMJY+>y85ABW z<(z7%JpG6RSokJFfvY%A38we~^#bM!^3L;9N_CP;kRr{%Vv7oLvZiu5+o2@i^4pIz z)j;Gg4Fq3c>D4k9@~mlrQ8#S^t|-_y?uYqtKs@uTSd$X_~;1~1=Q~Epj8Z~ z3vo^%&OGOZy<~OJS*(|2tB?z^p&=jxL_Z>87r!g<|M*V2I`#Mo|A0ZZW`O>XQHC%3 z93q+iHH*ilI1lKsdl3BRABp~OHLK(vcUE2d;$!Ul|xm+G-3>r_#wD!Us^!>e2ZYQwi))0|AKRvL@EITOf7 zgc<4Un8Mh-9|3>)R&3w^-qVGq2!Wv53xPsc8so8QGFdfxp(dct0f^lTF})GTuRa7N zR;Yyjc!38x9pVH#gZ%O}KQ$LNm#Y38RUL1lGYRK83a@_l8D5=l#!3Uu@cYKAa|Thm z#H&&a+n902uO4Atp?OVptt&^{{`!sAg(T}MomIWVIn!%@?f%xM*~Z@D zk$EpxSz~n2u<);FyVLN)tjF0WVXRR@n0p<5%sAs$18T~BHg)A^_^#_qR@eWOTfh=( zV*a>Kh*9oa57#0$7Fzvkh{(MP`!LjI{4nb(j!2YyE^}AnCz2vHrGEGt-jRyP+;KVa z!uxyZI(K}iF5aR!0LCW+RBjyPk%Nu=Dieb{Ry09Q`-q+Z6b{#MA6q2fnLhrPBXu@k zm-!L#VjXnF9q5o^(}=#9jH=r>N2%{Yro*NL$B^syUyBu3?~SsL!Pc@hmC$N8er%q2 zNrkVa!l+2TLNEf$g%>L|svn~CiizS07a6>ZP!KHk`eWt*h$rkXC3}9he+l~@H){;Z zx{Ed|rA@V^R2h_N5YV($oZy$6(Cv1v9t~X?tU^va;=!*Vcx8oFo3B&z0CB|i(OFz- zbQKq59vkMmp=2#H^gzfP{ajWJ^Uj)>H|Q+0&>+M{8)E-0TxZ>lm|7V}&055K+!4sFDsx`g0%ZXFAYH$xbqOpX z0e;Jms#q5zAh`{NfQhUIs7yQtRL)-04OeAry@laJq_Sr(83xp)0O1N4ZJ6bEqJjZ6 zqJlnv<8>M7q9NT{j(3logleuMm-EOX<>1Iw>>hG#TnQl=BO>P`BPHj|+|zZ&1^5WN zAexp_?m&#fseuL2<8#_L88=5-Bcp9jLnmV@!mej1bYBQfVZHB%v1hw0+(7nhi`Q^N zPeNN*_elL6{BSj?y|;&k6i1W!NJyrK*M0F1hQL&{bPo(uJgfrL`hmWAXMTosGsF=# zX-8pW&EnfsxANX3&ntvy-t1WAN$%N_tHZGQ{Ak_9k~6ZqRL7FsROS|xUII@^)!l<+ zANrg<#(iYr$^AxhM`hwOgH*g27f7C>#?K65W0T~*hFp*x;GAi=rjIk4N%1o%z9b&w z9*vRt4)z1!KW$U756?Y0QZ-n!nq#v)fTMOlM4N!a7t^0L+1(bXG)9l!X&NWJic_%}rYBM!Za*LOmLhUbnOQRk5kc7jjt9{^|g? zjS(OR0Qitg{f=^b9Qh+yz==3$C04i<;tDx%s|gR>TEfM{V&4tFVoM_aj^$rfzXEh! zkwdr~%r}!l8j({~M=;Q)k$&yfUt;}Q;RU*{Hr+%y9p$9Y2%VQlN8yQwh1h4$7Xj7$ z@p$%_#lDY0Oh%XUKZ6*>!}8#@{avq}a9E($Xeiz7>?N1?%Td5M#GGHbt+%#XN>GZ| zqxcehgc2=>nY8gq99OSGx_~;qT+E**wm*X<+VhDtF#Mx^94xtk zHZ)yz*pHg&NH-9R$NG5Zc*ug%83Fal_Wg}6w{o~ zfohyNFNK{0>Vw@LbDr#)^OzvkY>sB23j%8IxBq3u3j-=lQ+I}I9>v(8wE(nWgu8JV z1O0n4|Ed=eXV}A1#T#)NK_8^7a8LZo5pDR)pT{;?;o}HV>^s-so+`MJy&zbvZLEPU z+_q8w5L!3ZKvLCrpVrpx_G4F9?2G(l>Se<2+Ug~bn?H(u?`tSsFIB9U{h!3w%hxA3 z^&-VPQOtTd22|tfWz%lfOTSM%^>Srs0BWX!hWYL;ZXlNrWgO2RIDyM+J|e_g!>AkF z>hml{JFc5wI+G1mwfY8?!#NJyL9K9k0=Glgj`~s8PC5UoR9M)47DvngH`OY-T$S!HH{Euf-1891=|8PI8RO-Sy-IC7G8CbFs~1#1EBR1^3Z0rsm2@M`;c z98?4Oao+b7^v+h82ftQ#xg6G}C`U(Igh)A92$QO*u)H181aQFhSfs3QfX~%@_Cs)V z35*5-?X!J!eOK$6XR>dt(G~B-vTdA?jU!R@@y8w?YwbEu^XuR|!Fwp?A&f8xgzjc~ z%RY$wY9rAZM`B-t=3|9_;1L_uL~au&@-i})W;SD2ZO!aMct^a*;xw1+^y+;%hy)pV zt3i~akCvh{4t+(+3XjsGV`fDA=K%gyyhP6<8tuRHchogv{=FbhuaL#1fv6%pWMKoA zeDlDFqA#IRphpbq;u=tikw(U->b#E_zxmZ<1Jr_ixl;D)aZow7&P6VK&*JgQljxNj zKB5bzt9xnf1Z}Jf;llKr_)zc(GAQ<4e8BWcJ3oSs)+_p34NyN3I`~1%9g4-6523Sh zou~<{U@wI+wJ7xA#B6*{R~zP2ahSWX?*m5{)e8A*T&=I*4iOFKHo>!~><48i(Ys*- zb}SsxL-2^=#Zw_Y?8L2R2A_6ZktTM;7Q5;+&mqleph*J;zM=tPpff=^7B8Mlkc-LI zGfa-^>U76aJQT(3j%Su>r_o(gV)g}I>$Ybd&&F_#9_CAiZhp0b6~aZUPmmF5$E;}> zH*l|@0cZ*X3cwlyKsK?mYm+e)j$hW(CiFI}A2I7$WMS0`-;!oy6og7QDec^s^RHTn zVZ-jh#)mJXap(_HR(N`R=Sz?O8v7%Rmr}Otpk_dQ_5r47(j+5gwRzd;bo}bQNM>wG zIgax2GyJ$2q2wOIr}9;0p>gzFI$T~r^#x!+-9VOZH0SCsC$z5z8nXD#Z^kpCQ!Tsd z0;)ZTKnye=?X#zlgG=ga%5^Ixm;?}jNl<>yRqV|^W#924Myv?GtnwgTOQcgZQt&=P z`8ck9sAmV=tfCD_S>d(#jikfa9j&70BXA9`t@G3c&b-9esW@35H&4QB3c>Y>UU1-&%R!=rMk|#5+cWzS>NR%N3ri#fX15hRMyz+_aK0$ITv82qg#&@ zXQPCRmXh$t0l0bH%#Y*TzdSha^v_MlwA{Qi?kmlH)=JGOZJy=C zp`8kgoGaVTV`-Qs2kUV zLP=^TGg5*J$f*NJi4dRf(=B@k|Ef9|iR}jg0JPRt5qBzE;aom%Elh)J;2D)7NkG)e zm4MUJ4Gj1p)+pK5H-Jk(rEjmL8(50vAg3GX$!l0^LLDD%5w@J+*Q%YqrZb*1p3GXq3pC@_ZFB?A zilXGchTPcrK|B18jDYH9?wcn;bso+JiE0P1GV^y6`>8Z9Mfz2AvTlcN+0`;sqGe}w z3?ZZgDQ7F9<`_^ZayZOxToH_Q)M8(fCI>oovpa@vF(_F02{Bfokcee2;SBRhqPUq2 zry(w`6h!P#(tV%qf_%k!{LazzCCg|Bk z?RK?ht&9O@WZ2)48f&R&j!fYS;-_#_=1LXkP+wCNXYTO}9`OESOT2e=3GvHpdVvmN zTsKiC+{&s*145(;+ee8IsN$sPShAKoZ2px=Q53(Ci;#m`ntqU+{mdDH9Ng1!3LMW0 zKZGf(gf%$4ZkxbtCJe(GTu0mytpite!HZ=f5@%_)Kvm#AkoYcTIyRh`{+=Qwh)CIQ zJ2B=x@EfWFEj)|bEm0qoC37gSzUb&==D*D@wKzGPJ9M;o`H{2g*@%a!lpz6LQM*3~fQH+#*mMj0clOezJ=y9=BYy%11#2Sm022|5A z^t)x7;dlK}6ORcK{j#dAXJhg)p$1sk*6*nXVOERww+1al&G{G(dK=eAa8^{{Ib6>lOmc)nKE2Mq@j^ApMe2DnhBgrU{WNWEN^6Y0v z^Bo=x=%-72oW(a0&U|dByI56yfjMqKO#?BTcLSobaop!b=|vLI4XZOY!PVy!@*Z%H zR3Qv1zWuCfp~61%CI~6qV#{}@qTjafD`j>@I-008e>UwODHV#_K(T5qe>3N4^3sS; zClZgO;+d;kF}1H+OWx`cVoBHGtPb*YMf)UyOs_@FVch&7Bn7aZ$N^()g+HKoJeDX7 zPOimzPe3JL9S156FRyM*`xd&qTqboHQdan)noXcLx2vEVeF6qy$Hk+m{OZ4E952ASiZ}tTVGX0gd(&nQ zzo{Q^KayYFN+Y49IUgn(Fj+`kC}UO58!&;`R^+n^xdofBStw?O@(W-Q7(&Ok@4VH_ zaWEdnZLfU;^Oe{fPO|Pt7BHMIWPfCz?@;nI$cHDz5xN3ck(RZ%-d7?Y)h+8QSVtBN|ef|Mzyd5Wf6=%oaKsaJC-mzMR%&Ki}%7saTQc2?29dRoTkIOC{2U&K|)7tlVS zc7h^pu|wjuuACX;T*n&pMO+;=+b`)EU{|Z?VWh0^Vm`;SniS9K9bpwTtVV1l!vr`H0L}}c_-a`e`2H9ic0Ujm5Rt;d5 zd?jlQvTA4i4n|q+Wde8)0O1*YU0Z=yxa*9bdN4vImVH#iN&cXi1VIFnr zjN09>mK;!TyJR3A8{&gC$;j7~xPjCvf+!>@L zLXEzB2Z9`}y8zAupg_g6-B(s!TST4v8NN>eEQUXsQYMNErmE9p{ArKGtj2~Ibw>BY z4OQm*g{_^Et^) z0U}oWh{uq!9J91kwM$-Dh}!6__Ym$ZVJqipIu^-l7Lpeu9~;Xyeg(lbwrwG5)PD4u zDfoSDtkr=Oy8u&L`$^eeONDUci#t_~m_SZe7>>48EQ@CYdt208Xp81fr@-p(X=EJd zrU+)lO}VKkRi)7viifHA8a;$A1GyD=xf!CcX0SX=VNa*9`XHF95#fcj&#SPAw>{*^qM>wP;0y~WNQiI)E_K3WEkV9tgw82Bb8(%n7LjF`?s}x{M1tSGTtnY@ww(#} zriS9XPgyUnbwRhf;m>BbjoEe104v-XeUlLovwx2e-AMi_O@6AOkO61br!C;4B&+Cm zAXwp_Ts5#ncmvJlMR()&8nPj1b44Gk0J&%$b@yIdn5S zs{j-*U6Ndx@*J_SKYRf?9XOj=+Y6|6CDO&v;8+#&@Z!Dp_8m2O;cXYbbW6=`61qe9 zsAVsqLr)1xGrkz`jDW+$<3LQoLVQms0{P(}X8asL^39A;dE^Ygal$$;Oyx^dH;;s1 zakE8Muy>;*Zi}qsmP)Q1e;iZtREp>gMbJN@_4&b5wvVK_jysfc<$wlaCl%gmW>5*+ zIBx4jtU8`WtaKH8Q#wq1_7@G7LPj+TDSoK?MOBk9 zeEU9M-2mD^wg(bn{=oj#`zl%mZ1 zY=QiZUU!iH?(OZrlKch7gceUWAVsh$-(+c!H8_SM|`CLK@>-8e)LXq;a!m z#$aR_Rj;+zA?=|Kv#wrd2M~8wXEvS8Dp$q}yl#EWk90L->pb9eSdD$mTU<{~@OWw; z^(LfbW%GcGXpr*`^)qON>Omef0Jy`Ma8Z=0SEx^;P?ZKc2S5OkNqw7oabAdFcoAhB z0U2RuKa@_)Y6sv-D2l?xEbL7Mu-P(08|VmG?Q{&(RpAFdgVe>H{kB?vwzK%wVL5STCJWDFWyRucM8O-D&cAs3RAU7q@axyNc>lUMP|lJeswvO z(Z1(br=up&Tg1>-liqhLL|yY1u(ehABO6_f$n+}oAfe$1!ASKp;(+P^BcIv3xt8=6 z3q5@>fR1KrnOxz9$Q5RYh&9hwh<&laMx{5%Zi=Nr1j~LsBs_?%)tDwq^xX2r>e%av zeViBjqd`*=F4{C8-_F@ox$Z@Pj*j@o6eeO2LVml7M59* z92bi=S6{rMeIZq;<;G|Qr2&l0{Ad4+9>Uda2T^w|XO=T>_FILU5vqmGGgbc`94es3 zkyH&Id7d3+@vzzOYtPF<-@EV}9FxP*8ifIMH)IQ_!_SH|v)R0@LZ9yG{iqz{OuHyc zrpRL6Bs>g(L!&hz-E0l$Cj>p-0p)IgIxr~nYmZF>xolEQZn3=22cVYFC7kPKZABI< zf#>|`Z(}|s)veFUH+C7GtTj5zufI}gu5#AWz>&d@Xt-}-BzJ!&d!;x{q^NJC2&nuw zQ9s7BIj@-w=eBJqDDD_D!dH~xEHH#!SkKn{wS+15y}hya9=S`X9?wvZGtbu~^6xX^ z5GsIKqIi1_*@Xn{BLF*TH{7-AQvRY|FoOo~h~O4Gs%G zL+N)?`srzAIg~nBh1^s~0pYx!C6*w1l+Z}fWw$pLE{4lvp2k$z+c72lSzVhbITQ(p zBlR^D^>9=CG#jCnA80?$V3e?|W|soS}+PS!9AIGDvX`(;7>=P6SAkA9gh zHtTLZHS;(Kr-}CKh5#CDa(27W`OrYuA;S`1EG!=Kl!V1KEIFUORdHcD+%Ud>_~Iv+ z_yX~b%z07{dhYu0&L@qLVvRy>JL=_;#wx6Yy+Z6>*vDuZG4NyxU-hKcp2EjOol4Th zzNxRfZ7I=>Zme00=@Qya18f$(LO!{mpc(_YHR&-hz^ZWYL*S@;*d<)zMNJ7drWjL2 z3@5fQr$?OjG6JSrDK{a`P(yhIDW52vjlGciURb-n#}dhM^>q%54yf5rh`zHo)T(dR z;M#>~MtU2c5c`?lL9$jNiyA*oxfbijKFTW+xkM98 zfT4&zK^gt29LMbA+i3M7$MsDWKFG}Ln387H2Q4g}CFr|OD(tyLGAt769wk!0h%C^; zye#m7FHN22VPU9(U^y<9s0VGQ*Ujux3huaY<^TsM-0jlmV-20 zeyTF~1w>HS6N%?%2%DptBn?nJsAd~KTMzCfc2{D^htcetbyjCj)@3@Y zrzh(ioz=yYb+XPn!ILGYM-@cznQN&z5i+}ph8kkBoCB(zQ{VZKhzo4+TX?bz{y9g) zZ|MOxQl@#bjFbaBS%%A5o-D(qmC1@pxph-)PAebqvkR+0y?WxM0gt0y)R+Qv!;2J| z0#ukOK*6Joq@oYY&@NMe?CzlxNDctLXNS07PnszH@QJMItw2EC#$uu+Y>J&8k)~)S zu)U1Xp0lv&K2bQ5B}byxl=*jdD78fYx*+NQ>*uDo=)nc;hDnBuT>rtud^9RNGOmzJ&8GZhsmr)OE*0~@I?U%#HJri0S z!$TdGqw7e_?iAuyaHLVoqFB6v`wfQT&Wj1rIOe=^z0ZU=miU(cUD$x)oksC$u+G-3 z{d!RIRyjA*ibNjo_z&40%7AS8lp+};6ZMg4qKbO8JFEI;_1H52;+m&cm(HM-Rf`4U zR+U4D`k|ZDd8lnMf!T&~44gXDgUa-Li0ziC>y|(*Po>KMonhwjf3On9ETMH}o^s?D zEgTm3qLxEBPl8!o68p3UyBs+cT8|+(pzePFjN3VYI!ZW1E|?2_23 z-7z(MknfZ1jevKii#pEa_cYEdg@n%o7v|MCWS%oSBAoMmPLceJAR>~;I~Bd@;782D{F#UJ5{KE8&Fc6B z_g>j68FOd>hGlahImQ;>9cW~2xfC*Adq0>LluqSZfv0mKwR=eIN|)LNt~%L{if6ca zSr>VEX#pIR+S=08A@Hwa-@PwZZ{_6Oki7TlnJZ1%UOO`+bQWG8z#@QM>Ox@E=^5R= ztBqk<>{xKG82E5BB0rqc_K0?F55Z;!7{mG1!Nq__jCU;B29F?-wSu;o%6NyWcC_7{ zgp4gZw6h8uQUDknqt$HF|9_?H&cmnq7idSP32`wPTpsLVtBR`@Nk@i0L7Kwc7o4VG zEDhRufS0d1Fz%o)%kYEi5kvShLo%*Ykxc!mb%3Kn9&CYeAok*;GZk9Ch|OpcOYqg? zuTYs6y&?T73TTs_MoML;``67n>-zs_cg+KN`V46t%H{GV%2czNyO2b(xJNmAgsBeMOu-4&^j%Rdz#_ z&zUKDQ)ws8n1*FS_CT_ByH0=G8FTfPK){mXNL7IZUpT#u`cbDmiNnGwRQ}G+>OueMeex{^w*%Xops0#gFJi3FMXU*D3Kcm{XHaId^N{b#ro)x|yzw(_CRwDSN7*K1E zG~PXh1K!gMFyP$^0(Ej;%k2}wApl&$I4a_JS(=_m#C|}mo6{w?)6p@m##%XE&QE0h zu3vy&RbQ6kS1a$;reN?Gt544EO?_U|o~9QW*xKDf*R zPme$5z_K2{x>-MFi_hH~Up5nu0rlK`@j0=n>s*dMpJ-6JhH&}>oWiw66|I3zK+im} zzzsTaP0~ZG7Vph6+pXcbRHshPRj%Xpj&X4+3BwP%8oAZ$`+oG;--_cL@2D6GJ`TrQ zOvf8MACC8xag0D%+bZOB48GI%>yBhmJFjE3!Jx&@ zpd^L>VG)EtCJ+f^Ou{B0Op<}jkYwU4EQ+F#s1#DPigkVBv$nQ%ZQXrU)YpQqYN>s# zRDDnC^1LxFxU{0E{J-CG?{Aq&0?+^dk00}!-?`_Wd+s^so_p^4+l*31#bzH0^UFfv z3~?{7cjzeI0+oLQmD@T?ounp1a5ME+aP=2*V{_D*t_(L@(sau?i@OI?Md&v4cXV@^ z&#{jePXVv524VDzXZc3DBvEM{c5w|dWVTS zpTl*5S#txQkwPvg*g=Xrd*+?|ablm(iT~v$FTOps2K;?!HRiyxOctem40;Jou~vIv zzn*EX3(>9^`fS@|Hx*APTF3Q3Gw0-zF&8fIUK1T}tS9S;^W=omR`Vh!lzxL3e$fp& zvw6q}UY#kzls;ls(;76bLHWFP5Wzcr#Qpl2A*t z1L#bZB6J9$Cppkd)WwAAJqfmD%InVHZit2oHL>JzaQ7WoUJIBGIR|t~f&SLs7>B!P zgNe2fXtp*t1$T9o``_RJDECt+o6W%3xPOK>l|2lC(gSEcjeRG-Bw-2IzdeXXX?U2YO02$Cr~q? zF3IPcasK;Uf2~?Lz>Xr}04ZTZ-c_3b_ao5bN z_H#-R_lZuVPHwvz<$KQHC+4h8{ z{Afx*hZHM@=pKe9o9_lxZVz)D?qIqB1+4H$9ur7f-I~T3hodnV$K8Jn8k}S5v7lpc z1mH#l)%qKX0d>61{mv}zOI+@2P_i3Xzxh+V9ioKtkb34Wuz@evI7WntC2v*wWDwkZ z7=p8KH#P|#vR*)%38W5Ql1r^LK}Dh!E}TnMOfcZl%Abxuj8>X(lkD|})=K-~XvFcY za?&^?_bYKioa)z{n$Yicat;^g-@*})f9nqX^*DuJZp?NHHv@w6{~Nwvvrgs4)_Juf z!pfY-9*)~zJGrCPcJ^M?;x;3rX9mxGAP>sjK5tUXy3>Q6L(}Zvkk9tBaRb`VYkC`y z_-6L}yVdoA>*@J1eWX9|n}d(6bWVjZ&RDm2{YCiNuiPem=DLq?6ZFpK;At$mP5Lak zO?oF|WJ_+7J_ol4od^ufN?LMz(C~FT*S`+{e6J<92aS~5r1gGRuy-lhd-p0x7K?+N zsdo20V>>i9i+?{xq!?anZ8L&?Ad?YcmDd>Aj0mg!8@7;A6x=`kRIZX zJoQSeeko>36}sGzdT=XyzoDv=jfxlPZ4p4B;?*dI|AP^U{0XOYak* zx75%(<{Cq9lA(8^~E+##!R0@A@dFh?$rFT&1 z#SOjFZ2l??y&q_LsP6#M`waSHeYbk)<$38nDD;LIdVjL@@lCs~FAf)wKhXO(pmhAJ zp*O`#ugJXMLj#5CCMUyYWavz>^q0NT-eFz@8yByb>MtR78L`J+37Bm=dFBNl7cPXm z$djH6KZf#$Cp;a&$l3ln6>VBy+@2?2Ou>dz_{l%tYSZ`11NwT%?f>Qa>Vb^B<6K%`CSL`M3U+?+(RY4)UA71M&+R`5gb2 z2L<^T8OVQ4>EipS2Z?->M#fb*tHB=n5r^tS2C=ug8i<`OD1YR-pL;Q`b4b+_gP%Gm zLFeS5@j<;^*fe7BQwP)VsRIwjMuX8y1&GnV;bZDz#$}M`&bFyw3H;I6_I7N?+Bxz= zs%PMWdR)DLzcSE}YcE@nO2Z#Om7}G)Hu5!Tp|fuLgE+E)8rKEoEDiCu-D^-j>Vooy zjnZaN4s=23uu*Ca${vGa8yv=}2GWfk35&*3v~k~JkcY8ei`<;fys+B^`rG8>oZT#z z8f47;Wt%HyBLw>&h9JKr%Yu(Hc;`V0-Lwd|Zcl1C%Z81tHiAOavHseXGi7R&q|b)9>S7kAx-jdv*k{mfseZy9I@iVOr8={ot@=$C(9IO zIhJJjc^Z&86#?Y6=(ui%rBlN1t<@q$)*Q1JO^G> zZyH7ahUfYFpOnOAOchZQ(JqphZ%g9WS(5m^w*L89D08LM+=#)mt~8g`aBjQ(uWdlZ zw*g%;}o0aaTxPkm77$$0Sqo)m_B-Gqe}xkXfT!^oysr zm}@d%4Qj7i!stU9OjRqY^FBs8tj@tML@(5I{H>mWI2fK9kS?o-jl{9o+?leSU%b!M zkZwMc*rG~4;9I2P%&_qpy zWp3(HnSh4ab3I}MhpkMLROTVa-#VKp%2=Peq_;lrB>wN~GjEt(pB?+``aHS;_2K2| zR8H+GfZX&Fc297K1z39&9eNqFn>1JtDx zS?!i`Bvy!+wHrxPGxx%b+<&`7=a%m0urfZ=6mvL4f2*8=K7_@bA^W!Am8OOezb-&W zi9=x_cU0Y-CB1nHB+q@$-DNW~A(EOo3c3f`WDMyQFE_SjxLKR5ZUYxnQs-U*IeYh? z3-km)d4p9Wd(cjLM33lacOh#$wPTITNck_A_RXLy&}RW94+eVr= z`noPCSJ){13`&zhal_HG4Wy?~o2Qr{FWP=c6&PfRjQ1I)k<&H+d$0#a{cYR4IlnN- zhYGdtJS4&NOp4(?gLBw0yUHbI8<>~7|L2JKWj6DkBI4HX4(K@UB`$GE&$#R|;2$C) zzR=E+<7CNa7P0SdJ`gg9h(BG2R<}W>)&lC!?EW%rqCKu5-A2SY|89q)ZEQxpo4nzu zfZl18a_oqBBIrvv>T`IyXi*EOGKV;1iUsISWPZ@qAQ#rQM0e%$Mwk^jdg|1nPfmoB%}|E-d`gXR-} zb!-GrYzrspn(A=zJ|lTIT>OTTLVr8~!-U9@3L0*r`z;O>~MviOxp2)FJOwgr>lm>i*rlj^n zB>?bf^ZQ2ir<@3B)_BYH>_+>~uTe-Wsh(a9q;tJ0<7o!^KF!R1f|pV^5U+16p=#Gc zAHRbwLJrgXTOP(Q|JGmOZ>(H83CdwR^Z=_x4diSqA|9v9vv-Y$)RzsI{RQ%Ptu%it zr>3x&ma3e_pf6VN{J0M~*yfG$Rt2RN1X z%?egYhRpOQ{Tp5+{Z|NW_vKyL9|4qw(Ufxn$2CRgY6f)n*am?p*K?|2=W{1hk-U?z z%k=dS>bl)G9mFvn@QvnEz1u`72CqZ#>Y3mD&C}%0o=Sd~tc??f?PKft{GxKxr3y=;LuUjv2 zKpS2mTqP~0Mo%PqbjrVI7J4}k5ih1b0y+Z0vT#Mk;t5=7)=$zJN zVILK|Ru6-2#<*EF_{g^%?? zvnJ+o%q5%HeP^uG{^2-2)vOp=p1T;0^|2h|VAP}pldyb-H8eTFggvM3STY_|4}9AWjiGzHB0eI-{1RbLG7_ ztN;XC33SEWRKSfjdJ3G{A2aS6oxy6>s%n{cuppq(0EsuC)wc(ooWq@*YnXFr zMos~JwG=tg@tEBEkb9_Iu6oQacP(?j4peuLBA}<4o1SeGt^)Jqe899RN5hj)cXP6OR#(4+;jsLYzJ(%*8m+^mZ;eiUN7>k-sxCgRkXSK&`Z)`6(NsmtcX^56T)d~LrIS{^+8E`bx-v2_U=eylTDdz@58b zo<4eCC^j{=SUvSitW|O+;C{%qkviS-s4d%@D4{DZHnQchA{2#6?9&%4-NNK*B;$AptvNp*lD#@HNu0`0&J&-0c@`+5RPnK{yGAL`gGgZ827 z16lyPoojl5yDn7cfvO?rxs}l0`U@0HY*q`x3}PBrO?ku?<`b;-s3l%Q70|H&(cD4} zJY=o@#0t7=@~l`*Hqj4$lR@;&#a)R079bLZI7k(z71hLFAQK5YR+)-r6TaRdjEg+5 z?<<3_fa(ol!|l`TYBD9Hn*0!_xPQq}fE=9#9xZ^UWt3F6fep?-EVA|T?I5F<@lXRb z{WS~kUenKG#Of)-BSD=1cPReKruaW#fE0gDE2O6XBD#}tWTtEV@E*8U=fWdB&UB6v zht%5_x#jACl^((j#Y1&shhs=R3lx@R>9SH?M|3+W?EZ_u%I2vJXr~WhayomI_9Aiq z=OV!|V<`dsS%V~-CllHs8y&)l&B2GHahXHYy3_TyGR%zCV-FQr15S?C7(Nq${of=> zi!@IDvWIPRljJ5OyUtcXa{xNnlBd4ju2s+0=A~GWMR7zX#gn>H{AQt0q}=Y&M4d1( zzL4?+-+>I)@j(--<9Cv6s5%C@yTN&lIClw7Kz;Nb$_Od!Qna<<8^!&C5(gJ z&j~q?=R6L^zAw~pB~cft%kS|xPw5aVAF^eI&k5t)6Uq`0JOs(cd8*SI zN{GGrT=L5kogm~a5qm9prww-9s zFsZ=bb~S4=7C9*H8)=80sC?K0X^#(~S$M{gO&O*ClVr=YN-sp|IIFSCoM4Zwfao~0 z65K^7ukK^l`7b;4DCm~?h%$L#O;SxB>HNy&U}%{Q9OX1qaM5KfV8c*XkhRR z`N$zx)4P&6$Xxd$7Yr28fb^T6enZ^@c{{z=z3fwmdED|;Lq-~SwtO9s)5Vwf!D zR(ZsQ_hQ%fJn{eArCE7y^3~U@IA%u;{3}cq8X!^A9*)KCo{m$&j;n!_am>q>{t#Ue z$Jp;eStRr~JnbEL92!YKp1MJ*$)Sd0#7>mvl$gsB@0;hAXqz*?YuCCEen8z55l_1h z)z{66MV<+ffp-dW7r&LZ$8%ZeI2P)0Bt`ez zjYE>pM6&Bh1mqJor?Q<47MUb}TH_U&fL;ZNIe08eH;TLd z1$i9xhe-B*B5|q_`a}|yl&Um8Fixu?&L%_1cKfYP(UQC>qi6xm*HisP@)cKyLzs3bE+jPSLwnVU3u@F0|*L zH;UGEDa%;Oz09L!D}nCa2z@=t+w4*{1$Tha9Z0edd@w?gwK5F`+hG!%ubJRL-o;GC zO=cTwl)-|z8#Gsp=C9{)CJq{}RcjTiVf)!*-rsU%3>WB0w!7q`1yci(kpayO`)H{`Pxq*+}w_kn9#Optux26nLW(w^@|rP9(c5 z3g{((u;iab=dmn04`vcvK?~J1zI!r4SYfpdm%CI>dMG2{&v9h3x!+V_6eTG`YEB0LRb+36nLBIBfor~=B zYXM$E>a7Y1kb%8WC#S||EZ?+&`;dAPSTPQ`b-}1k2$YNq52;&`4EG>~zNQOJo$4+w zUWWm#J9W{dkvC(WoilrWo$U>b#XDr8T&P@cs7zOhX6i*I zb-4H<(P0&ahhmaj>tR`Cx_~1L#c{Y$S+feb3aR^V2cdS~sU}Zsh#I1)46vz`lZq9? z0hAo|(rj(oeYMz(9+h8?JmPNbLw>xD{PF(&H zteLm9@5TtGZ4D|EQhz~F*gOi7yg;?x_eo_xt;+k-tffBt=Tzl$a<}yY&^Ie>s5^0@L%gX56;V5W=#jX@108|A`=-NB6Yw{2j@-bId$|3($&s@WW7c@t(M0Y?059MUi&`1A=}DH9aBrX0c`~YDbKNg?n!1XH(l>U7T7w_# z56@S-VR?GN>f&ptak0RDMx{brxRWX&s&~AR}*= z3D2_f<&NZgrLla2yBps^@X~-BytQjedVuzitKI<=+nfYi4JhV5bJQ|Ic{2!cXX*TB zz6ThmNeC;}upjRS?05q^U&9t-ZpTEk+F6qz`Z+dD(Uz>M*Sie>6Kh;d(||L0t`j` z0#9_oYiK6UQGi!5PtaLpXVTuHg6f9-^ zZi!u%yFi|jbLwar4|SJ_n`3>?A_0Zu&GbLD*XLebpE@DN8%H5?3v=q6j9G+`x8rtc zopxQ1OowB0F%w~U4{6@lkoP~Ax^{^x_)5hsK|~T>psQa?qz8!P-GD66n*rrE;jQRe zc|^i4O@BhyL*p{ihzWL~T19N52NB2b7u(`U_f;ZeE{e+(l{@{x0RZLs)34xIXav_| z;}W}a6iZEe#?lC0 zZOBoC3;?9uhWry=E{0n-eN$}6yM!DM$S51~Dj|ab8E!-H+53aBL4cfULmnUm8zz0n z*pS-^!Rch*5jNz9grHaQeLc}|xQ37;0QuO4V7nAP}xKLPzFYV)R z+eNl;uEdvTqXwCop6g^AGMbQ~faKVa(+I)f$mg>mSo}K}!>L%`R}+lrv4{3x3=yL5 zBOB65$jN}bZ9@~g8-iu&gRxZ{lzak zs5f{~|C6YtE@}=?pK?$eyr_R6>Ip6?u9O{oje|Pbi~3ihetf>eKps#hIjF~aQC}nK z3ohzVpq4nO?@#yCeh*P^c2Ns~`rSM&fz843c*{XXPA3c;+XQtiH{?Dx4`p=kI0QoqAwd;44OX19!vl?yj`7X4U18=lqAh+fc<`JnTzLBF`E zZ9hQ395f2189UC4gQZhYl*^TqX%$!AJQCzxXaZ0~g%}={b(67!8E5E>+ntO8 zouD(eOEDpJ_j%Zh$o1!$HspFhz}1&#xgvJG=70M$`gsT8@ZRh`lUIA|QC8SfJw7Ho zPfW_Hhd_S`sIJHKZtC#~Gp^Se-FgW05}ncJ`i+SgU0_p@?>6Cre)F+&H9zcWFtAar zXG*954`Qme^*UXp-~CoUpZ|wlwH$RbZhe|*ROD63esc8Dd8o=&JFbUhWtKG{1$4vz z*TjC7*j@z+^kG1C#f!Vicz_wN)*0Q33v`WS#LeXGz6Yg-_-dD7Af2OYdg~c9Pov@I zCWt;)P4zUm-UC5CSI8p-#LZYa7caeHK*LM019c}d!)c+HskR+*?^Iv4lyNt~BQc1j zfuE%bhSZL`q%jQk7BGMX{C*;;h;{fUCkVniO%Fs6F0cE+`ce2E2X6X6AgQ^Yzxz8* z8{%WG7p||&N_%`E(n{IT){R+@TkkS5-dqUQa@lc!YIfq((J+ku4TH!~IT(^yqY(2= zn5#oA28@A`sC(NFpoi}KB-XpLGuEf`{n!zm@5FqaZ^e%6d?VJk^R?Jfoqvw?>-=M^ zf9D@!M|bWt-n_5v%`s&P7m{;^c09e*{Ttz=B!Y!_8M0t~fLn|3sU7K$+uIb~fi@e= zp{}@%PECO5vT3aq?WbHi8m!IS$#4DPUW=0I5Ioa&S4#}(Z@qy{_8`WD*`!X^r1okz zXYWGU1mOB?i(WVUv= z@2v;z{1ArMMM~!wmT<<~IW?*=$-H#T~@ijZZoo#zy7a(UB zR~(nO|wq)ja7CqR^;cW{Ex9m^SAN}E=Rjr*cW!J@nCP<-;zEWL)P^E-g2O; zr(D$?7&$p*Y}}tRxq5Y!AEKhw_}jU#Yhp4~jM1h}MQTt=2e`gqCGM`x73zE1A&VuS9Y zt#HSFOs?44+PFU~mre5E7KhabMcW<6e1|Z8gexQ0hyAIbtIbbDqorqA-K}vgz6q)A zZM(n>dYQJ}=IQ!Nb+WO2%&bTH7AAGT@K-DyA z?C7hcN)zBt(pW&idwIsBLugP+DhnD zHAq8;2=qvGt9~6Qufx@5d6j})o9Q?abhB(`IP~NALN!HG`RE)naGna{Rh^?@#|!0t zYLtE*B(KNDj#QkifbjhS7!>QPp3{H<25^*mNCWx_U|{TMb*BdS1aNe0fcg;tXw~h$ zZ>8j8A&bj2&UXSB1g*w2;D7=2QQZHCEc*q(4`p*A8GtVYaCEG{8m9pt3&0PH8?FH# z8X7(|SOYo)5I~%Bga&A$r^N=U&*7O>E<56OUms!kIF*lAb)1Iv7T7R#0%5XEsokfw z5K=zEI_Whq0VH@8>QnuCwY-i{Z{t<%(y-eEHbuQc*drSDdz0-c!nSMJcLw$|!nWWK z_mL9_{co@5@`>7so=?1$Sz5Mn>0koW5>uS3FK zs*}bIcRE0SKXmU8bok!3+aatHcY_vC=)ZRF^p@w~n3iK)R2?_DYFxG@V%cr!)it_? zZM&bf3Bf9Ub{(ZFFqd0vXjem@>~Q-s>Y$1oZXIgs+g!~pXOnilN3Vw|l(t?* z%&ZaQdJ-6fBGl!dvxT)W$(8nxhjf+pA1~Fmv4F)wi%_P}vz6&vt<~l=NI}rmny1A&N5hwtM_k5y~A+_~GIE(XtB=bJ6yvnt~W92wY+YU$!dfIe4E0nK3ns{)$uQ#dR@Y|Y{5u7@2`pcz(Z&j?zA8+# zcHdQRh&hMUYx?~ZlUxUEc#q54nH#f(>hI`y0T_&NBy|42`^Qd`|9X1rREr;E?)IOZ z&rZaMS^f<&&jCHW8!*3)EC1|gPw?#Y!{OQZhkM#|>}OB-cDntv@z4n6U-lExq5SLV zY2zC-=YgHx8UM27o00hc;l-|p{mdq5!)Ka=?B^^4&wko?c7B_#{a$4NJw0taJ74zG zwnrPUBvfwow;H3hbp^?IL9x{oZfuO#S<4fVh!t5AOwgqY!aYk9mS(rhiSYm6r&Rw~*QA<0CFG)Gy0)~#H+B9fAXs+tNboJ>X%sc5`8 zusj@XOeZ4NobrkQXh)Xg|K_@gRU57k)JIoElktS4wIt$ok$PYT>cF9uTH6u{tVo9w z^#L#hoM>}>WK95^2I9*DiE#6Z2tcdCjnVqR^pfhJ6;33=YXc}Zx}v!$(ws8crq8U( z%rw6XWZJ@-U?xseyguC+nHWGFoB5boSzTkTuC)@i*4&!%ifU_mWkp4BdQExdoNBAO zrmB3-jA|>tXw;Z-W5$mz9y8v`pHNgZdi1!W!qLU!$Br2{ZtVEN@yIl%y0Ri@6wD4%0ZTWCqmNw>x-EuUwVR$9Rd$O3=L%dFs>Qmd?l?`4%$769e5 zLzPuE7P6LCTeB-m`Ttxn1l3rTWfqV^mF074f_PR{P7jvOtqNLI!ReJ%rFevbB{g`| z%&nSZ)yxdyPo-5;H8*J0EDQy$xpN>FYhFo}HGd{5XH}F}*Hl}kwC7M8)%NKiX;N*WTYNgtHX)rX!8mnwos4w6%Hg*3I2eh(-CMF zkmb=ek@|qB+ln;TH%5}l04f-0jK^C*M64wM8YA$3Q&iK*otYbmCjz+(ave|-W)`v1 z&0^8@rW`BU*ce$6ZVc2lgcISqR3w2GAq=GAag@-!!iv_zxT4FWVB3K;r<-bfdJiXH zsc1rt0gaUmG{;kcWV)p#o=BnExmpRifykPc2uiH?mf*m&MFyI~O_4x-Jfev-g;RA6 zkOySR1S|Kv?x|#D@X)ey3p`nJVKLsincVa zMGIe!CQ~19rG&cIr4z~Msz@N(#5!BKUQ)RuJam(5n^WO6MupL4iX;K`!i`wDmwWJ{ z&2{mnmT)RcGlFA+JAl}_0Vb_nZL%4eQ;`+WRvebMyfMDo!XJ==k+sBWrVgBXiZsX5 zDQjO8&YrVXBom8N(prB~%Sh!ldDuJlhUbs1c;>e1Xondy# zg6d$6CGL?vw03Ra(nun1mCwucQ@NF8T00{>^@Bblb&cUfrWVAXI_Bi+MBt*eDBZQw z0CaU_r*P_V>oQ}cUFtSYA!O;!Dv|`v}Q#i3QQxKj~k`3{6V?9gB zsHD+(Rmp5CH_yXlu2;$#*46@N(G;P#5RG`moJ7OWm4_%@E^QMC)P|GMIxS7zIX}Kr`E>_JiW*+!{8elc_*M7_Gh$F1|5PXs9_DneEk6wLINoN5DkT&3LMxTk18L zTNYmb{d|x>*mh(b;V=H zjvmWSf^KC|a~vhFXkG$ci3bo13bUC+wAJ;5D6Ybb)K{VSowKrP+={`!(%CU4x_e>m!jCggNLg>Mg!E zg`3x+*GwP|ca@mzs_+Js-w2OlMP#Szs9AL^rUYl<_y>TcEwut%7)M;W+DbYd#`p zgsszO&Yd$$hn_VhRWpJJL7S2-V@4NRv#UdV6f{KESgWJWql=(8Yd*#l@zu%EMOHy% zO+>?2q@(&rJq95K{Ie1x9;D8SbHEd=tR_GbA*`6&MIi=l>PfoZx(nPC^Tu zRs~}GifW7uN=q>`zz_iAgK6auX$26FI0Ivq*%(V8Siv;f^jR1Kgl1V~6_vm%tEjQW zDV3I2hbl1wIn(f3QVQG@brKDzNHTao>G06;TW^e%pC39y_v+}>kKa3U<@g}ww+B4qrtg}WC7#1Mr z2CE_cdKr(JCp1$h@A4Pyhyhs1wP@c>tN2EX(%Q4?;`I@9d*aam(vHP4E(NJgEm5d> zMZn6l0(n|MBdk!6_LzdT!~DXjuvJi-Oj-p|{W~I$F{NWm#uwt>DE`5}G5Tj2{&`*{ z$-Fzi`NPV1`yMY+s1OK_Dw|eP7%VKDHl}dG^wOeH)5aH$8Z({0#*Qf-Up!&l=%T`L zh2x5f%ZkV0@2KL^qQc_Qcn0xbnKf<VN?f=4h5KZ$!S9aNSC4X}Y;(r8Qk_9KBe6GPTmmN8fMdqjlj=9DkbQbq#=`L0I`M z(K@s|ObJ*4t7K&YQDr5D)Ogq=0;|wSto+(&Y6Qr(tW88$G+<7lZbYD{aMbwxqQauW zk%5xt6tc{MoZ_pjxykSf%-%QzCN+gIrqpBC^PO%cuqfWbjt$*0#K;~nxx~_4P++p% zMHG(#ndW31GX|#90A$A8a?e|7MTPe6NC~ci%EZ;j0u>W-_!In8ZHcq)0l%h+(k~5-@bETZxb}Fk82dJR`o50TIv0fKv-P zUTqP9Nx9HSZQbfbIG1!`sxn`cNMqs!^B;8$k-C-in|WsZk{l_qAs#YG7)g!a?zYX#u+APsbF$w(a^QlMqGi0r9jzF%nr59)vG&C@KL x>@)9vgST(Wa{2e2^R)A4KF^%0-?N|lxbp!2Z1~<6^!wiF`f2~Q@%BCYe*g)*m5=}c diff --git a/programs/develop/oberon07/Compiler.exe b/programs/develop/oberon07/Compiler.exe index 7697d9f187112f727f31eba8231ff97e9058ee96..5eb85f7c3d07bc62c7e7164bf623e9df45165f19 100644 GIT binary patch literal 307200 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 z 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 K|NXy{!2ba{ciGVZ literal 308736 zcmeFad3aPs7CzirnuM_2W|N2_K@o!p#2p1BC}^UI1_VWAakps|5EIv669ePKbd2LN zGwP`0sN*)S<2a6M07t-OMBGqZ;!0iHCF0iVXnyZ|s_HJC;EeM<&+m`#`*eQ)Ir%tW6`q*WWoJb^+ABjaeJ0p>DzTjWE{Qdbq%Mjgn*du)-5B7Y1_`^9>&kvs& zUvPHG;w6htTXMpgB`2M*aN(lbk`qrUSyH#KWWmCcsYe`Ha^|9wPZ`^%XoRI)Gc6K1 z`B(XogIC=;&xUnG#zuPO<_wKol^==hfY7R<2-wsAEoXesjR@~d2c-U2=6El8z?$ON zSo|^}|M@XCM1o74NE~$kZ~q%xd&+sW$aK{eC{jzrPOy%Taw}Pdxi<#6&6%h3wXw_y@wcWsykR*ae!Plo@50JhO152U7q4zyB9X zAQ7o(iGJJJ*;#|%&u`3+)Fe*8Q|e(nsc)c&iO9@&BvOK3b!IdYnO(7>t+uG5p)J!n zEK0Io3lco`CnmVBHxlHeKTqVQ(}}$F=0tw_{X{hVPNGM8Q=%aKTB0!hQle-2 zg+x*M*+j4OnpqW1A67KAS2TXmQB%?QNns+^Sy$Xy7Xw$#y+>3u&m2)$)jV}Xtg5+c zL@{!?Hs(Y+V-<~0mCl*FDi+B~j>NGVq9yt`Q>+pFK>ELj-tG^*-G#TOBYl9niQ%1XPe+RIaur`1+j5_VG@GXt zS2QSEfvT24jfkjh$_+@V6!3mNBf#vdG2Muy1R@bBv_${a_vgwU0N&jdi27JFEyLoG zx%AMA#!QZrYR0?M+Qv}C(w@41<4a>ExBji9TnVmZ8kOwOl;Wv2Ubp?r2 z+*f{t0Uj13gMZhfaFyXYvdf`aBz`e$%orGNK_mOPJd600@!Cp9$p6SlB zNpsUISEi!rlew#kMJwj6c3+1v1RI;#Ce&*^{|Cixo)!a77nS_`=%Xr{>q;t`mljtv zt*lt-=6zXlE1w$QE%@@5dGl?i)cR?qRn4=CtM*%eQO}B&X&IDkK8 z)jGv2_qCtA6jHe6xv?4~s@iWO2+ndJMs#({z*V!U=AA3k_f|Ev1#s&%Znk@Q5XY)A z2EZ^32Amt(DjM5!sBSxw6=>7sKv-Xdu|}NhJ=g&f1lUCd6>HiiQ+rpo_h9bTD>f|6 ztKNM>RnB?@<)M}3JenWDTUE=fVkvuWx)6F_j5MsbVvnEQ+aOOEsqZGAn_uDFwbnBe z*H*7+TiT{4oH39zMFpMuzLHwv7pB?ebaQ!ITE^)~f3a(7xc;x7nf z7<84WGIUbmZHjYsuKN^YVV~=tPwrq*S9d|(pi#L_>QbS(JV5gg+357yVwdkoZf6PV zh8D;+js826UtjJ+ZtOy33?R|^p*}>n!yuKS_;BfxzQlu-^cHM+ z_my-yc=jrZf|p8y1*<{E9j7)&PMv~g<^0{$)BXYY(w*@l_0%o=|LawCAgk)9O!rk~ z^%oM1QP6&KpvkIgo?Bdls0@vJQG7Nj-3LmQIjd%~*>u8CcS6IZ`K)NG`$wQ})~z+< zlEi8fMe6rdnx^%zMP(HY8IJEj`7}~K5tO^hRpRy!B0AgkE(wA`%Ys4cL0b354i6~z}Z``6%KSLJL(Vc^isYG?VhS`nx;a4~`R z1b_h{b!Z_8q!|z^BnYQHSS&C?VV*@&Ck1ewQ0>lYPJBz>X$is`OFIx9Uxm73G83oDRw0I@>pM7?xQYfs+-jBpKd?YgARBzLGL zXG>b52LWqVQeP60_x{af=_C!Ple!gQPV0^MThX#2@^A3bGHBD)`H?9zY7+fbF(|ny zM$+MZJ~`9}tu>&S`toalsAvG?IjJLsVs(h(T?X7+Jx%cb8k}E$yVLpyDwUV@Wd=Av zT~A;?4U9Ue9|3b(zYT$F4Y;3LOz;PcY|Qis^Le~S@i2m()Sv<s^6F#;v@PSM1S=+ zB6b6!SN--uM6QRpl8B=CRgi^yHlE?JSKiN2Y@VT46X%qM+Kv4~OLP;aRcaD&t))6m zTukCtL|_SY2nH!?FZf7=d4b_HZ$cYD?=4Khbjhnt$DJp66@=5>B5?t-a5B`$pU-Qt zrq@swh4qPGpstx$Pjqy4VpzV%7O>*C+6wIz7K>{!XeJWDKh%B(oF^Ge(x$;r4)}@1 zbSU>hQuxfO5LU{#xM5-iL1G3W{s~f%oad0or2W$m8uZe*pJTvFQ5?$izhmdTAZg2v z_~g(A8tM>R;>~gVsdoK>10X%nQ+*-5xvS}2GU{=N)H=l0{B_oqVg#o8BZ@RxG>*a0 z&%l*F|8ublpN@@+WLu)|<4HT{bw%+{sg_S6yFhP96Ion|(G_})R%vm5&%*A+i@R1A z0>e_>)!>%~vz>0AcIa4X{TYO0(hK>)5Qlg!?eJVUWI;+Yn0^A`G`TRJ>y7j1(?dA8 zn_FD%-1`!KJF0WusA?J74<)K@-VQIiXYO!kup>eD?2h4sKQoX)OP%br(xVJ?mn;VJ*>1@6L~anM~!%_j^p4!Q|CB zFI6`D!1)pMcK@b`>rgiwlTJCds)>$6NBR=sFRpt$I3R-#8l!874W%^V-r0+mHM;3? zj_$uh2loG9+A1)2vf#(Q{sfgCSHV&7XSi4`)S#FhP{*4ftn_cu!Ld`5s3|kNc`I<3 z^eGzuRzQ@9?$s!5sS(h4Ix@#n5s~RJcu|})H7>_7g3*1vZhA83KnE@3IcRzw#0(0Z zhpNjkgMve;Sf*5e0G!s|oa3ao1=~BVqb8A)$cNp16NwDboVu}i%0SIN*)>XS zRa8(g00n)JvVQWB!V?Sn#5j%2T(j{k3#<}AIIXA8|BJEe`rzk9KRJHgyMLls|KPp?C ze`hu)1+w8BM*3WcC|ZA7^0+YF9MIj{r`sb~f&;sd=KO?P7$6-iL3$vSr#?TK3wPtM zM83yfn^v${=b%stpT<2aBYlePLjp#U#^`Cl*ei43@Gd1|ymEF6O|v?np$iu;XPW zxeiGJCP{b6lv%)Jaxnlip_q*+wN#ApEQ-HHB1dT=0KmWLZq;C5#@LJTbI_>kir6=S zt4_?{vGp{;E>OeSGw9*KFW}%4a_}0KR`y2@GDz}!G^w5yiy_Xg3>Cnn zxPRy1Te`Pk-9W{!_p>lP8>ZJ-FDxBYQYs3GjsECv$?LVUIDmpAa-b)eS#F6gIwcB? zqlAK4+C`*3HeaX%>)iBoK0)>|Yrpo&&nbb4A6qXGO~CeoCj=&v`|5t~0>2&A4c9?a zx}uIXC@=5qn%s$kyU3pns8J0N1G}*@TkDl;*o8#24n2K5$&*o62>ZR`3UJSA#AHFGsC0{)CQ3611lQZI}2b+t(V-8S(X=x zBo|8CMqH=Ex&1tF09W$+p_PsA70`+{v_&GzmS;yT$3pw2Kf7SE>^g2%8Y8 zc(J`=rP^C+U+c`u_Pwf_2aZ6OO!Kk+8dEXCjd2 z564T-ucmTtgC(^6Q`gvoVfAe+YXq{F>AL$Q zTpLYN>4m;B+v;!%Z+i*XIHX7aKC9Sdyf@5>9W9eYCkM>NXsT6AC(W0xL99m23uK^2 z+*_O&oA4)vsEqs(>S;JjmRwfUH}E+uRW#?grt+GA&C(<1tPt!#Jgswzok& zK!dQL?MzroRMF!3;!I+I{cL69553`=%h;)w>xv6DbpXTxZ}Z#|4H#wtM*?7-S}bg? z{2{k`#il9FRjVr--_Mc9tK|_yb8VVoNOMHXz&G^VOJ&nDl?@-?4{l(3a;bO=+Llev ziBvZ|Q@vnAtS{KhSzq0>s`~T|6Y<35)SUI6gK>)PSfb=GyL7dW&qt64O|y7D-(a~{I1j|}f( ze&1nxv64WL>Fde^K}GSKz@j^do-j$Ma*X03@=0~tA8v{6i6^!_tZ){^ZzfpL_F$xl z_G(Z_DMJ~D?~SXZr$N}tOfEp**Gi!7ZlWLHjs1bQ9_LRZv_xNEWMf;5Ew?554-2I$ zfq%&$^cD@p$|D*%t!C}^Nb&?ip`2{PjT%r&Qv$P$eF-K2EIo;7$e^7$+C;(DBx&{j z3tMwCNU$8ft+CxS7Em!;FpF$aeOA7gS9!@Z6)$D@7kvQe`>Px>(rc6Eqnm@+Cn4)0~A~hOB4AVa-3=I8>Hc;ZE zmAeNh(W=*|5>0E$v6Z7>EHRYO{hkzo!kO`Qu<1ki_7MI%;_vSkzaIP5z(^SXJ@N3wx}kp` zd+lue55!OJ7Qc);gtGDfCVqIg_~Qq3gXh|f`vv;gV0j_XXW1)p--Ov>qt#(wN-v-e z!;Ccj%FIWIdlTq&rw$Ui9FbNX#30ultS9VZ+_s}T#we*ACsb_5SlRRvBB@jod4N!{ zGg_6{w z*dVX>%jjt>JOmvwG<_pNY@gxT64RMso7+hDLTQ??Ju7LDV1-BOUqqI=^K_)4#}KX( zgCva=R=K_LF-UV3CQ+U!P$zGa#!izCB73{rl89$nWT3vlv4&XBAShAO&^Am&8%Q61h>cVp+5(+W&L$VrQkQgF% z4YL;LxugqaC&(U9R-GAt5T)d8R?th%cUn$?mL=zc#4vXVfPpD4e}YLYzrS{Zepb8e zi>Yj~!N4yO=LzXE1u~G?|ANF=_aD%0%W2CjrKhlk8rYC+2nC68?v){wOmuTv&vx)E zo9x9XNR+v!0c*mh&wept2^`t1FDR5LUivoE#|vvoY$G2w)<+Z z>NoV1u0Z@#fh)aVD?qy@2w{wZA$=y(%=fR~0?6lhm z<$(_o7;js(kewg1Hd4LN)%sgV3KECAC&I0T5HKpzvz|r>hr5#yVI>9noGI!rB#;+( zU1+xI{^+rRJ<=4$j_gmNwQIRoBBz6>8`P)be60_ZxEQV#3SgQVg;&00kS@y?q z42F)P2pi1wV_O;AFm%d#J4`|1ME3>|f{vs|7=$W9X{UryC%flqlwf>U$z#2g(@xw% zJ2A*sDTICzXD+})yW?lN$Q=b(jXH*A!eeET+lz?L8!-QR(hZ6VxqhY?;4YFTG>zI&dZ6*>-d z8x@`F()Z0>H9kU_hV9QwuX^^U1cn&}4$SflV%2D$o9mtaM31xl9V#iRqzox)FWefg zb}!34dE}a_Y$B3T>IQhlwh$Ppl`;c=f~TjD?2O2^mjDm4#KuV(h#rk4J=P~zzo^!JSQ89=P(EtG-q`$N$XO`2!kQBv2Hn= zj?b#uSoZ>1eS)r>X0=9rOTQT zn6JR3k<4VLxlW92r!d~aG8eHr+|yYyG+%LT%+3+*o>h@RLgHTw!TliqKG^qz;+ zW!~6lj&Xn)OMSw>c@^@g%p7+4Y5D9W--Q(Ze3~dFSg%7(XmJwFnXu3ySbnq*P&(3m=m^^Pm z?^Xb}RLE=vhNO&c_U4df$6$GmK^MdFaQ@?Gbh8f=y4c0my>3z!)0gwFW!=w{n*rT> zkkpgmhp^l>PY69y(S3X9&xCc|<|!*Vk|%r;Py4+clianTcTCFZk@e_>Gnjg9x6D<; zk+PmO7qvN<%cQb>_3lsW0NZpSCaR5Yz}V|;1ItVAj6U&8~t@Z^y?x*|vO{0HdeyCOWaFHDD zZJA1N1;N&@VpYm6WQiJzC>-rMa5neYV~)W65ys4~ZP{NBe+)-hY#mpS;z!sqhv|^n zr?QJkN02}|l#+;hE}}80Jo$7EDi3`5e;HK%=bmw-tw1y{=^67A1JZX|aR!ynS5gZt zNDOrA(OY=Uu>B)6Lw1U--F1qpCLvoApNF8(;qX<>VrLT^c(bR$F(4DqHJCHeUM+m2 zh1*$BxC$Hs^n;wHCLpIouF3@_4H_|Z5uQ9Rq$T>{TufeIo6ozje|9OrA8m6EN^Ou7 zv55O2r_)-ZTNY6EPb2u34(KtvQEuGz663CO)3@{n#$C@(?3jMc$PRjeUU_b*_0<{o zM~=3v2gHDz*_e5N2#))@^c^9uJx23)0&?I3CMwF@!%>#b`(jYuVCZ-Ra=8GTf3sqC zAbxS7x`d09cF}|@7*>hUEWDFCAgTQWyYCNPSWC2d4%Q;D7eUSWEJUMj04lJfCSHy# z6NReZGpL~v2+Gvd#0xR`q~3>iYrYS5|AdNw>yG9tw!eew;Vqh55waiqHzu6|j9zr2 zI*WzV$zYwac@h&z1&O2GgFq5%EV3bt%gQ35+3s!##+;^z$aBz4>@jX%9a~H>=~yW~ zXPGHc;VUrs4{~;C7H3lxj|Fz+>Z74tKBBj*_9#V(vnME*Mp zztlaLw3?SmDKTc%em5(rjS*a33#PyU29R+3bzvYtwJ6?5%%^Z%s4ywacZFi<#kw!h ztqIJZYbLQ?7d_=zqb1*@O+q7HRC#a;PU~_lcX^84MEfX)y}bxWp*EthOY^Wvum+KK zhCp~g)fUCMUEe+2uy>6t*+5;Xvj0(^y&fM1K==4|aN)c2Y+`~>MTbc1I zbbvg8`y(`G`9xZD4}2TJw+FyD2Tf&@i5t3?oMUh<;|w%j==gCU%;K*{wPB63-KTXY zY0UwxaEmXBOTEf`DLCB@BB^@ou7F(j7C(-af|J?s#_;soB6JyeAz#k5m=1bdL!R>Rf zx_C1M&rgiS90s@6cL{FkyssEY^#zpJ3Z4_7OHjiib$w9Y5aOigY{Wo(g`}_Blg);m z!TyY;P6{t|d-`#^yF2KV%KR+QlnWAv zxUU-kOHYMlR}JOlDSW|6nSNxA+h3FF!rXK>LwnxP)-7{0+&6Tr zVJ@wYU`sbU(|sZs7hvTmR}Kg@v}wj8?(ajK&URO9CE+pd>5M@cN^}`&$7orv%=Cb~ zbFr<#tGeUd$(o8Vj!DBvkhyv8@KCIu?s&IA#~9|I|9mDJ=htpSXp+kfaU=D zD5wPT_7}b|b4`i{nhPj5H3XpJJ*o@ceuR2vgbRaSo%?4^O(e1g-AEv-bKE8!sf|)Fqx0Q`I!bgjE8PX|bRB8bG(@!C z-HVan!>lnDBTJXY`ZeCAA?9 z#6oLM1Q&XIgm_9f5Yf;^M2#ASNhf1#;iI7^nmpZjOKYv0rA80UKdo$piE0S_%LivJFE;BE(YW(WOm`jywvrWn_`D1IGrn=ut? zE7gnPu-<*1F`f<~B#`ua0{)@_rsl%{9@cl8H9#v`AoY!mT&N>W!}PiOBO|$c0eJ_N z!(;9y0?ITXs30ETPXss`U^LGse={SuU@{ftwVewvb_*k4(UI%|&|@N{jP^KGd5!ZS zW8No_ z-QhYahW=C9KC9NZ+h`}v)fuzVjEv!&(Yo|DoaPZLeUQt!fr{qxnAt$!Cq-?>H0Utd zVbQs`MBRbRH~{e?Zbs_P#l`A!{K!VGs!Oo5(d@bRaMRrj4UR|l0tBYJCrU(#IzkiJ zZ`IPg$|el>SNXY2cPEiYz2nakXTdBR$GY1S&|F>|Gy(;Q*}0 z5F`+l(WB-$a#InaxCxOi(Z1k`=f}q32f2lZ|9G?$lzvro7ybhw@Zk&$`A zJxgcLJV?UN{&e>!pEG99n{$}G_8+sdC*XGih^fO_N_YWv95|Y)xzH^HHP%@fV=)Tc z-H)ty)9C6Mc|Rh3;nd4Qw2^?GQF2&z4w)}xjvufT=npH*pW?W=DvV`z@<@%6N5rbbOc68(a$&wJq+$*B*qh&o`C znE(DD!O?8pPAE`I^uSp(|DBKjFXrDcW{w2TPtHx_#vz>LoRvHhD#??GvE&CD1do;S zKMIA84Ibz!f zW%fu|8>o38C>Nj#x1R;URB|VqkElfnGIreiO4E1Sj!zOOo)4k@j{K%>0&e2-K zv@8lSb9SmTZtVqm&XsLcSgy@tCS3~(G%oOIgs{Opxl`w#Y;!Wq4ca496VOU3$}!1d zR-mkHJ(vj+nk>xkku1w%Viq_@Aq)d6!R%FS!E^&_H3d=}O$K3@4e0J-2zXhq6!t$DVZ=OCU6enub9+Vrb5Vwk15_&x6?Pj46 zjUYu@-m?8Q%x(>guea`V>RXyxQC#A<2g%R{6muEVxY3!vaugN6O5Tlw4EdR5_dg=o zJ=3QQ#i+360oB13Wnm>N#e`6b*?|;Wsla#0O-uBvgTfW4^lF}r0ye`gXVqa*Tw>TA z1gfzeOm%?KPG3W?6NZzVzG(yRMF^6u7HAbVfw!JpyAxwkTOB-#&vA!&6}!z$_J( zmWttAkZ1S;6K*A=d4MW&pdHls@+_c;P$m{UjYs20*U+>URn(XnZSHrIz5`~cx_FB- zo6Fq@!08y?5;vy)q@-M`NK=upI#ZhFLMYE@VtEdFxDmMoj{RV- zQp=#{vceQcyExqmBK+Mbzuj2Q(4L)*dY{8)fZYo)wDpY1wy#S~JIkp&iCw|`$;^-C zum|g8jHxQ=NTO-YPmBg=7nBfc2Hn!uc%yF2v^4Gz(C^ZiB_@Ix+nBdhIJ>rG{59Wa}i=}<-u65 z2R~eDTi?A`@W(rYUO~I@3f61u-yW(lT28&TgBcpM+OhM3ExEf=d)=1b;fxne`C)Fi znj*(DwWd_JhZ;xvMqjLTr_w{D&}+vg#z8gNwU`sKx*;#iGR3gE~9Ro}8(s(wBrQ0<{ZAI3NZ znEZKRj*@}sFB2xpA?H)&(#?_dt1*hKdKzl29X>8RcA8s7P)f0L;VC=u?df~*-!e(| zu!x$chV^8IC@crLz6iNxxEQnpVRd=~M6(Q&e6i4)aHhlG59=&nfvk*F(VApOuP52M z9#ySE2B#(qg-sw!Uz*5j%VJoRT*(8C^{>yoiX1sLr9enLx@`e@r%QY zT}=ROz3rfV6F>!>f)xl!ZBKXG<5P@0CK$;h$T-)JAPZp;y|g^E3|D29A598_0f*{> zNBn=01F9I#Tn?-1$uYA`$Fxa`z^oE)7(umlN#q0)H3t)6er|7>pG%jqm?_?A=d?DO zYV#Oe3kFFweGVE+S^eJ0lV!FnR{u=$GpR|Q8frp~>RP=BOFS`kD%zj0(pg=c{xCfO zNlWTSC%IDw+SWd-OM<*`0vvp26_5J_WFP`7IdnkgNCIlI)Gep}bAU4^N$oD-oRwt2 zJ01_?ILzN1?v|m;1bB>-+8$3%>o$DPP9&?PfkZ#(9Cme5oAKndzRUOQMCWkS9!T`G zPBhL*%}1${y*1C+=&i%2Iw?-iI<36^RQSaV9mI{JLo;xPI#2z-jTm=FY%1fD+c`HG zRnzky_FmfR(7m)Qb{8`5kjy4*3nH0uAfsmrZQt(>)eKcRscJHMRG?(s4p)PgDQaLc z{*0>8n3>|F-VpwI8CX`5x8QOIldx|>k|Uhdq0Hg1EO>2J4k-UZfDyp-F}g5aX~>y+DHUC}+dO?dS@f?6&x zsK+2wnW;9r?4&oAeGUX;kM-vyaUMv3GM1@$0&({?J&=>A>4<{OlWVh4P{}`dHx!TK zySp(x?}zk14uFAusXwrtkWGkCGcTj$Wq(H}XPNo@{N!ipBN3JlR;LK7;hB0PD9$RT zM+28vuV?g&IoCh`@sKK~i{d@Osr!e`URh8yl*QY?&9cz_HZsAILVJ$Mp#*Gmpq7QE zFf2MyX%=Ozox#xc;pF(ZB-fi@M!iYy$7^H)Wu^w&fr7S_=_8ORr+#vBlFcdP;mMv) zX+L1mdL`CC7-Nebv?#s{3x6ZG#e1{l_NbT;_LixGj9mrBFoFq8eCt_yt+jpuYC||Z z@e{D9)*G*tPnCEDhlV)!%o&mI+_U|Nh7lt=Z|v-B=shA*0^54ez!8`P8Pn$6Gjl{f zzC1+xYD)z%W);B{Korp!Qay#@iMgL&(f++Ywl7*UZ7o#+uWP|up&dd9C0l7n*uKxJ zw9MiDte25lKir#6LUQRiTW<1bQ)$H&--a4iomA>6$&(Ue^!nLa+=ali*tGN;FvAv< z9{6JM5tS%Y#n)h!Z674huOFGDzgrAx=;bT3prIvYRTfo$G^_p=Zl=$co0(?J(sCnC zwgqo^8MIp?>yJ&!w35vkcdfAHlaDM?>HWcJef_RseBIXZMe)b}KXap}@4Z)>NJ#W}6afrupKlqmuuCai3Kr^_ng+7@i)B# zLU1KKw=E^#OULkr^|-J@X1e!cd-Z46Vcw}omRr9%sRzimb$L1*Y=&2a)}J_eo5#u9 zbZDJ36BLcT_wyjeNJl+ z{IwFs9@>C}xslmv{Rn?`TJgg?37hs1^z4YFklUQr2Ak?<1sz)Gb7f3K2|waVm?wm_ z+T&d747R#je$)soN8k(A7C^c9%o&3&{G|7jiW`;GtDf2mAp1C7&>g%eekCjMb&M4L zQzh!fG-PZ%ZVIRrtVYt*vPn*AEGXe#ApF%Ix}sO~1KqiRxCSB?=$)JtJ9($|dz8dS zKMypD+qGEko4_I6L@X_zZ}P>)P-I(IGg_-QzR^2RJG2lW|(P*DuUSAdj2j{&!oB^vQk>7lp?N-E;dWiUdmCaVz|H zn~Qr7nQP2cIw_hK3@bFV=+qhPof3dzap+#6gSiAv2L&W+kHM7hj9s|oUo1z~)Q#^5 zAGO?EFTMe+vN)HZ*NrU%P^<(k{*%!q>Bb(R1 zC2XRTC@=K)TNp=OkB3ZNY@Jm8J3zp8cQR3mYsPqR7Q2)&E{`O~K+07kxtj&I3hK4= zqIe!Sb*CY(@I6vEZ?R@&8B#HQV`e|>DBuImySEG~6dKR+ZfInUp+*5|%l>BP78(M%nvKYLyMAz-k?KjJ= z{pH(l&@04nM($Je#_GxIwW#wG^V4f)n?}o*d+0vF;L(k)YQdO^vpZ9c)Tx>RseWTq z6(r`nb?mDAgmiQA)h5(5n~Prdg@*EC%_%c9sRIltralO%gVbdAflsXq8@YkB1zBn3 zFo~a*oaCzMAx`|wl-7Huu3$c>Wze|Yoyj!%r9?LeoGcPJyU-ttb-rsIrIU z_NrTe;O{r1qo5Jtp!q)DsS?slLmbO5rc$&-S0fy!7(q7CM;-PX5{}-h z)3Om1Bo@kH67GEl28|3QC8jxuS)>n>;G|Osb6OCy*nRa!q{OChjY0N$3YYuvkk8rf zLyU*etajXV9o|jcpAjdOLmOb`y2R%cyTpCqJnYRIVwcW^hSPbJ3DxH77-g?dFGyVA z9uG>GALn5frfq1Gv~p^NLuYiFSLh`A;&yJRAA=-V9>C~3t!IE6+Tx&!-G{cB({6n5 zEZC(tDYkr%`?O_S*RlrjkhuF~07L_7kJ;3y3m?$}D2iWB;1wE(Dpx0% zm|jw!HR@sgj!jRjUl~5LEYKMBB6Nf7&BBi%pZ*8-nKmhnv&LUzu7&#n(g0t`Jmp0K$Alx&-P*+;P>0Z}Ryh++dC6L<{J zl#02xzNFc;V}$z`isKRzGr|qa?aqH#x$$mH_gDh`qmF@W*f*gK*%@I7c9BlnogjY= zEubKKL!efW>x}$QHOb_L{jmI}n`Ez0iA?oMmO1HFk{V{cqHb?Zh*Gc>S8Nid)={)U z=|IadDG26m`q|y3-w1Ufzg1n*L+1GW0c32`k9Ai3&AiH@Cb!`P!~{C{UK9W%*C$X8 zF($Z2q;_P2>rfu+bE&Bz5?pVDlNt&W>3a?4RWkM0?~t&eO&>Q%!p!UiZ-hs~M6K0} ze@8UbwHr167?n)+79#6#?LfZMoE7o`i!P1hL6d5{pUTQ4upW;S0j8vO$$cwKoMOni z__a)EA=juuhWGtUS)yAn%MOOjp8{moWj7HvYxu4^kepOnRvTue!Dphx0}b8WakWg0 zIl6)CJ>M@YIV!>?$H_)EYm9d4cGKOCuEsL9U2n1h)_KN@mFdvnZYE z3n+m4L^2*$;%^x@4{>=IqhzJS9+u8Dw+`pm?~xscogAI%k%)`dZ<8H|m3)2_jiXif zZy=Io3906npnj}1v8IhWTGjP#v6Hm&dM*%km-jXpTgppQTyD3an(z=1<>C(s^kSiO zX@cx$kUUEiMs{QSW>IqB_I3PPZn4YLosMAP%42s0-4Q}>cnVQjN}DBCwhqkZ>iv8< z*?m_JTAIDXl|+MQh{8GQPJ7jxZ-Z!7FGK?@XitfI)E&ZJQLa(a9at$Ff$0@-l#~r+ zO{Bo)*Sw7JrmvIs(zvRW{hjXJ>|B)eZhj>4ne7?Z&dMtVU6i36ztJRU^WfWw{bDO5;_-$Xe8=DG>b02=8D5csvqveXE z&jOF5om4USPiA#YyiU@+jxv|!yk*E7%X#<<9s~W?HiXq`7#8sI@#M4~%l8m$Fk#gi zHm<(OX_Ym<5CnrCvFD}8aGadR31q`sXCXGNL}|U+lkanG+M*?5+E-9w691@)HxjFT z821CLMmLXaE^<=$;>l^fgYO}3wk5-V(6EtCijyTy>&0DQLkO$Wu(3|+1Uxyd$8~{i z7bx4>-;(!EvBYj08V_#R(0S~JFIu9q@I_1f4U^fPtbEMi#>@mKwXMJo z>r!Du30tjU^(eo!WTnRJf8VI59?cc@ z|AfFW`#TZ#kcMFb?N37O4_&B@AgooxCOWAL1xDoxQ`?#J(Y&d_ld@}hw2chaax0XR zqRD$wL^E3Ffhn=Uk_WFY3+FM?lIbpw-E3qikI^QN8=sIoIG2OO`#UKfS8`hE$A|OS z#ggeRk1;kfl*gJcbU7wS9x{D7s{W|t%rN0nq)i_Rs&ni2PmT}Ajbhwb#4SZLLhpcP z)Wy@?m6)RV$&iYh!NwFjwGS^uW09jJpwoUb-Kpem%IhzT`V(2g6Xq z6}n*dHvESWV}aXA`*hMq=L3Z4d^j@K{glCR1A}{z#_{BE5a&&6v7wZNa$!guA>;yT zgdx)_cWG{m$(1qaWZVJc?vu#H;0FGsd)#)YdiQr02jTAMyC1&iy^9}MD?V>%l*Rns zLf_#YK{_qbpN3%HDqNwAKf#t}c~8Q(T)43m{R#!#J)vXZTe)<;gmK{NWVeDpIxP$d zTvqYF=l&GG%k!KPik)*BxE2Fe<$fll)KJP~pg_IA@}Xea@-+wV`{UiOYVp9=L}-S? zL#-{S!Ei{s)T#7;e(rJu$bpZdag_-Jp@wk}Qc!|BBHpN$$q(ACLyQN6mEj!(Vcuoy z8prX+YxVLxD8BouS>g`^3Y_I%vCYsM(1Ux>z;#cGGK*s5Y%+$;7_fIi`5eSpjb=QdPj7D%(N`G}APG!U#KL427KlTjI5zdsnW zwBtze4Qw01EEI1r_4AULHpEC?Ig;1?ATkU@yg9ntmLjW`XfK4B3DctZo+NoLccMVm zz}O*%u^hE08N+vu2M5r55nV~NH{XJ4ChVagY;VGL)G$#bZ|<)(2-}CSAFu}l)B;m` zpthJWW1d=~4{nDUDM#lb$_*1zn&oM{=QQfIu50}?T>N@>8OqvQ>qUP(@A@X{lY?cC7edYBaHATnf$?H^oO06aO!w^bi zn%YUncF60&YM_4oKwb|~QT@76UMti$Y&b2^7v;55ZPu^P$?Ktt^F4@tN?s3B>-6hm z@>-=H(XS86YqjEeK7j9(*TdBx^y>}sdW34xuUE-yjk-v`UMjEC)gt}cAg?nNk9ULA zIr4g>n$B0Wz16A#Pj03FhM*-nkFl!e;{Rd2!2ga8O>ur=hxB7y!;t4;>HDygO+OD$ z-)aK}#Z=oI6 z`4%L0(VtOn#-=au#P@C4nr!qaw=Z82?cKUE%KZUq?la(hyTb|L z?nyO;E=Y{l-^1|v@rzrK*v-Asr|lcStV<#a68pGk1Ltu$-i`B>g|Oe5aF)L!#qpVNp%z?Cb`>?qAyPj*{wt;>-7SWiF^p7ATin93}yFZVu+Nx zFR}@cEs<@xyOQsrqU)H0+}pMiGu4$((*_uk#Wa67>U(Adi5ho~WQgulGMw&K>38l^ zM&-_MCx+fow4ouseZYv5V*iLT+3U2%Q8s}g*348XRk!eeGhy>@Vwe%5De6J{g}9ydYG?)0mtn+ z`a_BCqaHzG-a=+}nc$GIMD$k6gnCTm;sJ9nCCCFaXS{A0QETN<=?(03!+#+q$2l-}DAYYgQIP!aT^V3U$ev1>Z}3 zinA`*R-{hXc_$?}U%e{9C2FP){sFE#uaJIHf=ksT9sH35=c(Hf3{K13YkQ)qxJfAW zRE#q&Pv9?xIrm{SF$$EY%&18WP#-RYM|T%vxE8WLIm94_7(`#SnusQiz^CcY6Ix4r zT0bFQ(u%2Th@7vH`StfCry5$H7({<{E)kP70$UlWND4)A|PAbs7KS(aIrmjYbwasd;qX8Z*7kr~5SeGK21?UOE%#Yc#r# zllryLz1XK)XOP>eJBVDQk%Iy}E;NY#>JlQVHDVhlHBo5oPi1R`=YqS#4w^ksQJ#$Qw3gAB5d>PO^jjA_hl8{liKL5x(Np8>?*G-8O8xBJfC-n#v*?cij%dL+=I_f$iPteHiofJPd=CmH_)7;`{JsG0TB644i z92(&7V}t0Yjv!)?M(lv;eWCSJAFr%08szqBXCl*#Y0L}@$n9B=Rvr=SG@`^wJ&Y%( z^#PyO0|wbgy?#27H)`bY0AJU8h`$rDR3mnDQfCOQQ+-;?401cwLgbMei78&{Tu9%} z@@Sq!I-OK6StX*mWtP|YH8JB`E=(XZfTJFUlKLc)~byS`eBhN{s-e$h*$f%S=YJfZ#b zU6=I}gB+}Kh+LzQV*>oWYY_d^I}3ogRU@#Ta+T1!%%`>1AYNXlx`2dle@JX<3V>PFwj8)RSANMxl(;&|kEp}B`o^R`~PUi+$Jh#aPo(*pc`-&-Tb zsC|j}k@HWDnS-6wCwRgZf4=Lo{%DYcR39Q=(#S&sa_caNJ}P|*5c~i*XjM3=KMJjD zeOfOW87*pgr0FM81yQX^_TDC$$z&PU|YZYaMAa zGzThvQq;XyBWDHpyU-xES8Ir9(TJm*RK3tT$ES6sL1Imh$dfek=z!dgGl=2pLLzW6 z68W0#q{@WWu0E|99)U+SWgKCU{Zy35 zXEpLTYu^I>X)l8;R+~-)@+OU(S!W{YQ(8ds<+VU;nSLHkd7KdE{~y@;2nu;5;f|btN0wP0*c@Hy_bhE z0uw=Ph{mVFU&SPqOpWOoAaxZ}1z^``*u8++=`*!B3o}!bF6DeZci>Oe@8j`a#`js8 z#_2+%EW*2l)NWZcVp%jISu{GX5WXrvvz#>B_4{nR*YN!d;8C0c$)iT{K;aWu*2gSZ zpg;&bQUY`FG)XP3N6JeCxSo!F%Ri;!s$x{8&e%Wg|I&r*t~4Pk<7{@OyM(u z_E1}df|dvnvGkc(n_mYtLZ`*Qt#4DMu*50&0qR)bUAcRrA@dBPptS=L{jfw2QWF@> z`A<-Jmg!TR+jUxh&!Cp*p9MBl4J7O`4SNnh_4msOty?5|n5;Rcmw?3cjKgKYNP3&Z zZKL>wl=M-E`xoOj$#mXL5;s^q&ba*%$2KK5PP9b-DRC6_-{h$Wo_;M)JE{ALH#Z}G z`Y}a`3Do_>!bMw&QT^e${qk?N=^JLSypqgMY@1#~8mQ50j#0eJb_Zk2OHrKF zC!goE&4mXGdFDH~RcOxDWJs@{feU^Us8JP6O>R5QcMxK}O0Gn|8?h}&u5R1t`d-yS?VrgrV--iea zmKIX!hl9Tbyh15}4BJkD?FN*1#lX;vATXHk$%>jl%WE_dCfk2_Z z0h{#K-}w2lBK`qeAljqnH=?tn)Sj2&@BC8jF{f_ij;8#?-svY<^QdF2!taxQfIQ&C z-ge~^XQ|rF#Y5Z*W^fbIm*G6uRTz(`7oop8@r3k>*|L^_oy2B0vA=f2BUW5R4cySh zz5X3cT97!voxobbVv;3$fg#Jd(TMXXQ-Xi=Qy%F4NV#gkneXTw?qfgu*;mTGTe!>PHr_-NvtD6W< zA!9!1I8c?(7KTlNh3-GO2F@?qAc1azVrF7$_FH10Xa-Rj^QDO;?$vtboBD#VO~`bK z%MCHr&DW8JuR=@Q3m6yaakKz36+=!6m7V58zx4dv zTL87UA4BL@iS)CYgt>yl=Y}Gb?|7J%-6KE*+hOqOb9jbB zm}XBW_v?aDb0cdp1*NYomA#)7g4cV|hC)0=@ta6(KB!qW{u7+9KvWH)vNXANsa5Hs z_{~gS0t~;h2OTxKZXya0!RE%V^5w`Og|oP1>w#`z>i4*K9WboJJq9HD1w>m0+zV)g z!^#GAV*|qa@c@;}J{Q+@U;i#)q9&rq=A-xLnVf8A)`BnR#>>H3VxU?xQy5da=(2oW zNqAPA|1bL}0X zp*8MndS~g|CZpTc*V`HNS`y%gpOF7in2A)M&$IbU)b)rm68rD^xpHLNp$kBV)vX~X zx<-V4t4Cj=Ck5%#GGFVbr`PHBX8J&fR}^2*;O}r~P3&{7^m!)q9fShx^?F6|4Fo@j z;9$pBE>{gm)JjCzs|K=KwpMEh`AyPTu1OoQy~UujbkKhmG6$>fAwXLpUpm(cS)#@x z>VFmThoqgxzVV=tclGE?^hQK`^s|KQGW~5#9}@D%4897%At6iX1sZHB`4a+9XHcLk zEEfSw)bWV&zOLZy*YNFnQT%IC*jW=b;{BFE+i0Tf6Gd}o&9Oq0=sZN*whZ1)+vGff z`zB5%V!L*6Bv*Pya8ozg_Kdla#5QW=bSbY%15XHFd}SIoP^1ZUjuT!r-n-W~7ReVv z+;fn^Xq9x2CU`!ArH9Ow9uk>j!!$3=aAzUL>YB$eEJnl~9mw487>nY$jO@$EZu>^x zTn$o3)@XC}*_%Lz%#}kT>%KBXblD&cF;^lDjD1-9#$5F${93}Zq#@>N%qxh{=IU#j ztF~kDF6L?w(=9|gT`9&~VSf^wYuTh%6dyv!WRgZFF7EwPoaStaF8>aLa`p95zudhC z-@I<3{p0)ydbJq#r}tfwpV%+`Z1sXozlPA^lyHw6b-QKIBVpA3>01M+M*BgI5+E-R zA`21|-18va5ZG*XECu+aFnFSSST?vs^H2uxK4I`A=~P3Md6^3s9uIKOF!%uX3-~M{ za4813i4x^hQK-|(k>(XQAPR0u75CnkM&qgqon{l*M4Aeuxhb5c+-=IvC$7`nhBR|m zl}GgD(a^u}0JLx5GTsAGua!a~;o$Uj3E$*aNmM4s z>zJQWn-3SolKbv6a&b9NoY)NDozVV>cLIlm&(3mQmWE7URuq7j>2&uoIM9JiaZ_%~ zpkW>Q1An+5J`A5BTWy1I+`7{;=-baNzAlVEQoi#V!c!q%@bJ^Z_?dDQM+i@ayUoK7 z3gc(FKf>P&;i<|=5C7rjP;rlPpAX|9W8jYlURU7b5iCFP^ zQzf!}i3yBWv_vO*$xFG1Z)AwkccI66A}GEZ$J8P26l_UauS7!5w=)fFp1?4dDw*c12Q+NHi9Xo;R)kP!b4*tQ{9ftsXY&l^~W`Tc>vkeH@csJ79teN7Q8OsFUF zOc8pj&*@;dMBg`5)&+k(Sdm(*VeV$l+iC;5PcqFnnf6jQY1q{!`VYb1goX817iicf ztj@9OFE_BHP>TRqf~@_use z{m2i~5?K?DEY_dbT#M9CX~68trkBuN4qs9br(2g^Zd?<8+K=uR-9Vc1q? zh7#g84G=dVz6@y-+p3ojftO^zUwb~bZ>T@d0A4(U3?S0Yc|NE&L=e~OTXZ()3M!t4 zfEa@&wc6`oaNcd8;o$ny!yLqf11Mdwnib5xnAz{*W#5Zl2TzoA&Au=4 zV!;>dW$227B5jG*BLtGsywVuNr~{`Wv~%%zRrr~n!L$VtVOE;R_vqSk(ll$@02W$( zd9cJO@_}v)U%y(vRPOu53+J}YEC=t1bb0Hb9l3k691^nzF*OSFr832legFn&7GLOh z2FJYM_(62i@b%h2kXiU=`6e-o1PEFGo!>54fD{)a1z$TUz!C@?fSrt-7e>Fdf)_?1=t!R?E0h8TVT=lnV<~#-Qq)v9e@D*k94Yv+6vPj( z_4xW7Bno0Zwnl6Yi9H4=M52kU%rP1Z|17_S5Wg+w=;#@unqu zGx~TVgD}7In8h($%|fCNmn>Wq3d|m}HA?eI$q7=*F1a9bgcwiup>jH>Dfd#XP?sVE zHP^^oy3y$OKGGTuJ76^$Qh*Q^Guz*zL$PYZ55%qDumsHh1*xbf)4r5i&Isjzo(y7c zR!@$O*=nvk1VE^NR?VHytfnBV8ucbhA(&8wTtEP4yK2;<0Hluw3ps`=uRqabLrLnH z}sGFfkNH;?*p++V@2g!rY@Cu-5 zA-c$O1<@5iTY1{%+C;9K9)L; zhf8Qoy{tonX)w7Aer^>&nVJ>oz>GLcaO{T%%Dl>YgbZ@_it`|Jl&!eA;lv$A&YR0i zJ-CGS)bJ94`}O`9Q+$dJ1*DJyj*WkB9=Q6vx3o75ATaB&6=$9{clnvzM#csyB3ezV zzhgJ$e<`?FM?J-;dL4zY5Ww$1;dB(gdEuU5Q#E9`VI*+X0YA2bk7WgKqji?^6CViA zq~ox;TxZAb5(Hs)iH z4>&JU;6j13Vh-mLJcW?UPHObTRdIScGAOPu#s+JU#TvaJ5TyG-$4faO5<~s-%J>%6IsXGzvwB8a* z@+Onq<|n~NCUBaCkjBh(Cv^~B&xfPQce-;l9NSYX@Z_|vWJP&(`8JbC z7pa-T_9UFW zD+y`HP<60jQ&O?I{8Vxy%x!)u#Z=9NaHG|Q$@5uVU$VM(X6IOo;3Mi!PC5+U!r;CP zo{Qj``s(Ci4E}<_-$G;32P5l?CF>Z-I;~6amxzyvc!h`&Kr{kT-%pct8S^M(g37j5 zvuun_ng#s|7tM%?f@Wn|8cur!E*`8EUcV;c6G`|Y6y8w!jFj&5DHV1@DHt{ZNjbzY ztCgQK`RPcG)ymRJ^C2moX*M5#sX>%6&iW=b7TEQqY5h)O}UZWc33WQT%3zSWbaJj9!d9MvUychc6#Msn==Q;b5%~4Bhso^v1XsnjT7Uq@*^Jns#skEDT^qdxuyE zWWr11-N8Cmdc5Xo=tM31gBbfA+Ncq$W?_V7;YU~}VL|tVkSXqh{sb1?4sj3?r~Oo~ z1p*T}arRegHN#{ajbg3egkoWcO=qhmx{7bj<#=0bN7^Kwqxz#pEpdfP<2IkG0p{&E z&<-=h-WxvB1hRfOSU0X0sGdQp4Q(2Tab)B71WqJyX8`F;b(X1?Ko)wd(2yYWfwp`Y zQ*MGu0;`3n)mrEbw&*>sYeCCuZNAZ;DaSz<<&tl2Ld5z2GfC%4O{bi6hC&yO0i4CS zb7}S#m#Yi$ljh1Y3UlKdT6J%2L!gArvRS=)tS=-EGKHG27yMj7EkAW)H1QN>F;HjE zeMTLc^8-uT z__}DdC8(Rod1UNDZZD;8)R-CSO{8|2Tdy@=;mAyu+Z1C5K*7@6Nx>U42k5ZL3@hN2 z4CZmjDU1N^fO?$cCNoK2TZ9s*IjC_A=zKP{gh!K0Pl51-8&ROk$mR#=G_(T6xq(tG z08M|Q%4GB+Y`5Yy6)Y$6NlaGU+J?P)JZpUwo|t)W0eJftkahgeB*}XgtnM@LE(Y>T z2Z2Cj6kpD8ZZ8SuAJc;?oD<(DWoX0vK}BQaCsfufhBPme5LvT-kOk^Qe`X0w6^#`b zSLgM>Q>@tIgl+`XR#DxdzG6MW$VVB8W9wKXmC-@jWV}mSiM}1tvpKqG8T9;XVtFZo zHz7T2E*`4RW!0b>%ygT|hnT}0JjYCq(wWd1yA-8oz57P&c_Q`#0!GZ3xPSrt7h|{4 zv1N4my>{^eWB!d@qO?o69~q26TDyQt@LQuIbdy@5gY|nrS7fG*%~&pLW!G1Wuk^8s z;}5ZF4ri|zGa2v>A_T-Ac~vsATUn^ApXr!C+88sJbb+cujU&k=CPEul z^l9mBz(M`QVa z*gdoi+7X#xDiC+&OP$V{gczyQ9|(NeHB*^>(BBXQF_um_wyFsWtNx{AxUdF;q7*Z8 zTIK#|{po@qi;#Q1M>iMluUj9YD?xJ+gbrM`Tqxd9Vn6AWQ-2#ipdO(0@I=d_dLd`7PnqS`AB0bt1*k0XsN|EQkKw*idv)O@=vjJn;E2wm8bU%v@f>2G zMuZXH`!9#YH`F7_gC*|OA)*p=4%2oczF2wyD|f%-zH$eM;!KCB+0Crk;>0m(4hA#9 znk|lRB5TtaTomuk97lt^H5Sy876Rr$(X0UoieS+ME6DAccJt<-2qb7Nf+zy+Ur~bt zWJvpF2Id9=gR}>Dv`b05IYe86&M>rJB$-E1T#rQO+;L4Pp>IAm2n zz<;tFiH&_`gS2;J;bJZ~_OP8gsZ&7@#}e_^H&7MK<2Vo$DVh7KY{Uj zBs2xoT=ot=7u*|QDrj$<)DXzjX?-rl*pW<|w1m5sZ6@RA`?R?~!8xNJa?=Vu!cAYNUT=h@PBDkyIi=u4#PU;>!WtVLp)81?e zcP-m|#y9%3F=3QlHY$R9yiX##Y`lNiE%!-G%qrW7j4!e2F@6iy+ewVf^Ak_fWt*p5 zbb0PacthE6Z3o+TcG-CB&Rz4q5n9)>B^ZAj={KT9HgBg4VKdK1D!}Gy}6ca-K&#qqLq)b0H#rmnq z1F@X=Hl_>G2T_0P-DK}Lx2dXU7&eaeUOz0^Gf}So!2o`2uCTr@Ks>;rZe>_e{5)pz z*Z0Eqi#|WjWV}P%QsN2{Q&lY<(68V7FPH{Sal>!xEJVN!3<$byO(ai9mA$Gj9-&If?t!3 zb5&1GV%Wh5n}N^v_KyF9VWSwv*~c?6``A1F7{dlJj5>Or=;#v+%VAhi`~{ZCVTo)j z;2Lte8en{t_}4(7|ISs^7%s~JoO^*rsM7RR4t@I?&94p_2!@;h0T+&!y* zWV(ZyF2w3h3?9ee5UYP;a4~~Jta3hCwm4-OKSECqFvdz{aCU#I<~bW~zU3)XW;t2PJ?&+e{RwyAf`UB`aD^ z>>!)OcIvVbx_ovJMk_(QeUthyntP*wZ9sh^4 z?*Oc-$ofwqB!qG!HS{2ep=q!!s9*rmL_q^KL_u8<<73q*iJ%5TOc0S5gAK6(Vna~` zQ9%$5f&yZR*s@rN2s+niiCB0x^8fwL%-nlli0*#-_xm>7ciNmeb7tnunYnX~DtdEJ zvQ`yI>w!gJnTeJ_j(0p|{R^^?N_c?F!@Wm<$wy59N}_E)LlL;Y?>N7YTtGoRLCpri zh8?>VGlzLOTjWD!_Jn8BVIsfqB%k#{vZ|fJ%9rCrj|rY0g8l$#tA{%kHMQ*51WegQ zjp!+ufE!#w;q$-^H{fT*w6Q+OkiGFW&&VdJY4v}S^kR~FcX4Zj-tsyPnyGp(L%YLx zHYl1*h9jxC_W?1ORG=LJMO9?Qea8S$h)D&N3Y4izBQICbq;;D5a*D71H<+)o1_CKWwWJv{_{6VO%Up4Z5jN_=HNhMcmOqh{U(>%o;K z-@??UFCph8;1mN%+X-lRP#7X6`68qk_i2xJ7I_bg;T2F*^6KyEh?O}B1|>}KB$QIZ z7as*n7tm&a&~-EP#1NREZX&~Dz#2pBWzYA_R7UJA!fU^C2R9YywE~q?OIz*h4{XxD zz7!(xl`fsH_0LwRD^8aEfg#_v;Pj!!>z~KzpD2@iIfKlvilp9nvimR;zlj;s91$;H(dXE9tc#s^E$YD-+cz4Fn)BI^3 z|E_MrKUMRmX@^-%{$2<1BjPw~xftwZkaGxv(EuE(fk$c}Js-e68rVq#IV-7@w}m-b zgE$qbQ??1{r;Q?S5I}Guy#6^0CczqN7`5}7{xPam@c}@3WjGl`x}Bc`KX>WIKCJ1{ zY!6Xn19AJh2E{F-xS@@SyUd77gg8{?VNTc;NoN9zl5>0)7($4Nkxa8IcE5io-vAQu{82nUZ-$SZFnxhGzv*QT5OI0Z8mhZhl&cC6 zQqk^WP~a{EUQv;n&*{nKhaE5*s@a`TE#1mS!+4@M0gW*y>+fpB+0kexFM?Hq2ij%v z`UtPSiIi4kr1|v~@I*3r^_4N)YxorM4G})iIf`23Guxw1T5m>tkGdtPod7jEg&#~J zjP(@iK+-*bNcBu;DWG==(mPe+&NnmGmHAZAF9U5nI!dF`75obo4mBW*&*_xUJrz7jT(8X9_@7j+XzUs|;U zIGpkGg$Z)+@9@!;#5F*?2?Ufe9aLyvBuHkZIE+DR+oPngs&!^j_mIMQK?3!{UL3SN zV|O8b8cV|f{s-x>!E74ZXxp76a`ZD`{AM~(ggFI044l^Z?o8=Cwm%(8_I8x)trP^5 zKu|#98Z0_=a|-(V-+YOtI!-xrHh$fDQ8Ew51jQ71Vg$X+7sCVbrb>sAvy`01Dn&=f zSfw}dmjKUD{fi~|S5`yo_n48l?Fsa6$W!c@?u8)057RySlew2xE1TbK)#JZD#}6{o zcE^(J*I$F2{~+jV0og^BfIcE9V5%@>5!3VTos%V3n`yLn;2cZH1S zb?H^?{ydBBb%@~FYA^+kYM@HIr;4Bl2UKwjv{{VJPb7QGpg!g<`-USya4g^fGWY$c z7|GZzm!ORRVKIy)vEoHB!Mg^K;$VqR`B#{y)MoO+rD=E6&a5QzC<6h4tmO1a&IP@} zjv@9^jb%Iq-a2jWvBcz3WLec98;N+>vxx1dv6-)nry9Pqi8(}LvJT=qhu9zYi`0UH zu;&u{fyQPZgguYgH5xnJ#~N2WpV)he*JVQ+&L4p>V!PRIFl-%g+b<&UrsF=KOOcg^t z)Ur0L5jvmr0XgXZ+%ICjz&khw%hN>e0*&SQ1ODgpUPA12jWr*YGkpIfW}?RQKw}~j zeSa}L4ewv*fZ$RR3;}`6sNyBY>XV4+Nmg&57Eqc74T3+`))(Pz=vvi%p{|K;qR-UmanRO;6#^avFpm7?;Ji&5B4L3Y1DHMiF0CX` zc@rH$3r9`JHY3AK%Kj0XJKU+)eU<$tFbeTrd|q&|y9K)RZCyYqGE2z#Iv8d2^Ffb` ztj313z>0nrnP+IqG!`3~1C>~C(O~g5ycc$;8gdBLlCi_IyS%b65`1O}CM_9N=PZyZ zAvl zpv%d*Ksg4?u8tV(dRr}jx(-b2+}U>d;miPgz*SE4^?ZhuQ%M=HW~Qg7pf3j6S~D_7 zVjuk;pg+<;pc$cFp}<46Kshn$VKx$zqLs>lSEiYrfkr2AZXiJ@>u!dd*T}w2pN7RK zGy!0~;3ME?0UkZ?0*pexa}*NT3c$ScrA$IrK_u43m$yW6@d+RU!wuxfn-U>{b&3PT zR6xdr)O>j}VwA@6L@;!T9hl|ChJGO6z&!E}84n~H3A(y>;8T1+PUuH*xYZv81hki+ zKx^FB0l$5Y9YEXGFzpy<+JL9Z`TT`iegjW+%J=GpJlav>Bh#CA(Z-iGD8G|ezM#j( zmTwGHOU{0NVZkAXju|9tB4mxMmI|+y8OzXqPLVa(#*0}g1(EB4^j1ni#8Ps36R-%X zB#2hkDdxqPe8rPFN(byW(bx40mOoBQVx+?C>t9AH5>^`(gt5CY`jzzhsZ)M51pCG8 zVKF~o-wFyB=yn#+XBxy!kfD$LP03FA=Ws@qvI!FAA};c5{Urr26e*$xx{{g31TzyD zGmZH?Uy)~0j4}cmqd^RmjSK-FuVusr%8D{F3Q(8?t;Q6tlJ62=G=jEj9i zqZA__#7XID|7~ol27!>guCN}|>~BNv#J>oWDw5iLWL9Zc4Zv}jPi0xImjs^u3jmmg-*tc3Q$-|0W|M-lQ_4t+5I}b?<&AM_LgtiU|a?T_5=6dF2d7gR@#g zoR3}$v>6#0GS>kW=-I~_5bVi&v)!2#W>NrwX7_I2^gO{SpN7T^@z!681b=7p4+THA zN4X3=dOxcreUEOA(N#|##^<|{++lI^#LJolilbIRGKF0)e;^Rf4>X9U?1L}hTzzEPyCR0G=0Kr4DV-{|F`OFPbhBR+Hwne=99!lI98Yfu|Vi3j$ zX?l~UuScT?I34O6tMw&Cil*?Ia6=kO6r&3IXPkDmP3R8Nxg;HH_}v)5cLu9r~a3W-Zrx7g3yu!JuY2( zHMeYcJnB)Hj6HqytT=!Rlc5NoeXSb_3k$h;p*ID(H5*tuoj1Tc<&4qM$Xqo}=H|z^ zR@TWz&~Wo{rdFIx8dN~n@R%(J1C**T`e7$pIJ?Dio_jFoKP>04@xgio>z6zD)nU$E zQte@5#}RWiv{P2QbuDAG+lNyj4YYd?APhCZD$R~%+Hf$_BF&_Dacj_)UavlxwwMko zc$_SPjV002BZ->eqZHRoQEGltYzzGVw5od;`?nR$mxN4L$Ytp~zl-;(05v`@&}|y3 z>X1MVRLcEA54eU@UjAAHQqz@#!6=6{Q;v{LYn03>x9_T;(lE#X6v#$(vCevb42gLy6Jp`gWdbt?77bx)gF)ckktS zfrbI)RN(h9w&>CNCUjI%h%UFR7#KL3HJX|WnBHr^9-bV&{_J))av-2tz*@(6R1-+` zD~_~6(d?YL{w)a;iKz7u8xf{kC%I7H5fJG9aNMoXyO!eqz=7C z!uGfA{6c1sbpVKbz7m4E2}pmqIyGNF%>lxwH=-rR@1bQp$c6)UX_b+Xj0Ufz-xLq+Cc!eF26PJK8H&(6a-@N)Av8_Ki8%uO~m~;^t~` zDV#PDJ&da8`t{?yzH3WWGTKNVPK#6d2M(~|g71pnOz!4d?R1Hq7%1q_#@h^dq*FnM-P*@>_ zl~qlLMN@o%f;zu}z%&s!+6o+TkidH>u%|CDaD+}!DGdZ}evH-q;|fzE5e=)Yrd&~1Skdw#ixwTQ>kAZrk(M!?iv&vWa(zjZaJrQ+%vUZT z;T1~g+PH+~sPo=OP(!-+k$iSLC9f%EU=K@4geAl$XpBQOB$YCzR^O`2}uOxN(*U92)|Quk%jz3Ie1q&X^e%) zO=W!XVT6TLlcpIU$65$KiV#W#9U)x- z`O!l7@q|z}K=xY5SU~W5{{5cso)+RKn73Mj@Bai#Ye3dp$ftyG$XH<^Eh#n$kfj## zJ7~mZk2HemvTZ}XL35L(;l~n$rkpg+3*1#KY#YKSjFK+3G}j1?ofLzcR6o#fKHmxL zy_s?!L2nZzxesPuLp{|}T>A%_z~~~c!9EE(I6hCuQG(y|_ESn&V@>XZBRyuHC^6Sk zepwZh7uf4lWwO_22G(CmFh;ZTFdYcC#1Q;Of-FtIqjkKPAgXpNh?ElkAif3gaCl;z z-}o3+-yty9v@dwH@-}Mizr_GX!9+x1?z;lATOa~@nV>+Lcxt>YP|(YP=7j3oK)|;E z3=8qRUrd@NiKR>dl6OwczA>mkGEsTDH17zWw}F>J>`@v!&fjA-%BK?BR%7!RzLp4SDHQK~aRXAl&drV2zSjirpfjS1N@D5Ryx&Cb!470_=V zNkEjuMe6E$sS;dLP!XX1tAOZG%3cNP{}>SUB;_1Z>VQa!J<%&x(1n3wy@04FaOuV2 z6f#^Fhp-**9N`-R9B*{X2Fxf`fc`~sz#Og@b zh!pTffKeico0#(f@_ytaK-L%JsF$b7SS*XDzp|CQ%X_sHV*7=>n|rY?*Ep+yMgxTC zUA(3#J|%?ez*z;wv%G)ptbr|Od2hFgmd(}*xJw{%mlt?HdtdCr*AAq}JO8jn3VJ)x zw#djlwi1t9p{{ihE1&h^5EPIf&|(5D%k#RhtZ3l{{7!k8xucl5LtY8a12qh8W){;z z@-pyolmlnIp7zN0z3^fd(h*2p3+X$eKoiMQR+W*b(j3WSP-nV^y#j@~W>dx_irMj= z=o*Ny1iT(#;{{&Lc?`g?UPjh?3~M82MNQUF$O=G)+<$b0vC&Rm&58v|qi; zDg1a}FEauQxTn@DLr%hig)ISBk@t_2$r2cUUP4$FK>xJEZ&o=`tIH0?u)YpO)Ztlh z_;sE}(8B`C&eL)QG#?TLsxHA@EuCmer*Pl z+bDH9r22l%21j|7#7qQ+PHN}$*nw?6Nlwtrc3_JciS8glC+b{~r;eH0_(){uR4xVP za>Eo|m;KZ@@Dj@Suo`el5dq8_RCh=t(N=m-fXt%|b6}#9caHB3Fh@S5WXsiH=gF%k zUf{De_VidoJfilBWBYRPOpoy{dTFTz{j?|G$MciEU zY67RnMbZn|%;o%+jnDBSIjYEU@Dv%? zwRoofEFhk|K%H$J+%XLHjkn0Yg6tJZ_sq}>9^Aig7R;uMcS%&C%P1Q3k^(S%r*tJKhG0XLqU~R&|KM6;#g)j;r~taB%tAi#{5cau#=e6 zSe*5`@;%xu%^>wL3HoS#WUo?g_Ns*@agpB487%u6%;?~U@P`~XudjmTYvl+d&yUcj zOoQ#FuutBU%F!vzR3+fo0A?B+M-Ef$zDi(c37-Z*Y9U?Sha5V-*%^<0mshzOH1!Y> zH&Jp~RTeHh0;U!PnCa^asXwq_;)@(^7ZVO>BkU!5q*jXuGiDLnXoj2>#kErD>RC5X z>!#2NuTRI;8n**@q3bs+V9$1`cLvG0NUIoGo2R}+B0?+iEooj78d06=RJ=Iy9l=in z%oj&SDR>UpeT&u+eXEw7DF(V8>(E9FB!ricurUMuKrthLH3mWfby_WapaJc#3lR5q zyD`EJ&S|I#-Y}~|ONV-?U0-<+aV(Mv-%8{45`Jx3kYkhP;Cb=Z>|VTH zA_G@RWcYL~Nq4_bC*6?OOJtkNZB6}Kk#4F_hm|Pbd~8l|0l}Uf4Q3Y-K-L$esf$C#I`r_&IQxpnXiSm()B>_k zbE{n0MdZ1nFb5K+vONb3T=^~2Mt_RizlCD5r{~Pw=qBjlBmsAB9O_XGAl191(kc2Z zQr4iE(3pu%cr%`GnJ|A_xkr#=vCn~lWTX3-=4ev9sN@un@<>t^`INZIdSj#nf|H7` zF1gYp%OcqsJ{h|A#>hC3H7$Oxq`OBpkYtDZWZ37}7#Rq%K?j+9s??5;$^huR8kxrLoiSa*RvU|}N(%Me(Fg$*RE zous;FSy)%XdJ3$-!kQ7*USOA47_Wd2brRSZ3;Ud~&H@{5VQ(?6sz|zbwvK`@1GNtw zDr)qyBu|0_v0FvbBu#`l48!){%wg?AJ*1Gl3S)$PE1|C`21Ab%egZ;5hf7&6S<0bQ zF;lo#SXf`edI@Zag|#P)spq>0QFUiZJ4e-*oJ(|MW}<>AY{}O*OG{2ir^&$(Z5A_v zS`HMNzd$#?nV0@WrrR|W&aK7sAYoLM(El*D`BT5#0&sh~fDPiBHV3a4I_W**> zbS+dsRRm#mrZq5wIa&ng|1>eD;ArGFaduk^#LfEXlV6=mvP{)1gS31BT?`NuEafq~ zj-G;o8UvJ#cFK7}llg%q&>fW8l~NHbGB}kJRHi`$8E23^$n8b0j1B7)zaOU+ zMPvCw7f|TdSEb&}3W;tr@PPuYwxFK}+Un+BgucY|0j=ZAMtYnrZkiFh6S%*Y!scb0 zdJ8BYAS=6vCtFbG2V{HomVwxdfv{PKI~yp~)VrwI*I(Z4Ptiqk$y~&2im}NOGJdlW zDi&lnfPN^@LF$di(RKUz$faa?QIMH{rfVw*bUC5bLEAk_;xNGQ8P9gZkhj%bg1#PT z&vu<@t>7rE)+8`h)o%52xv>G=bzrF;XZ&M{c*i-ZjfUpoLtc>X@7ZLk?>+?p4dBOB z^4|O}RnlqYyMkG&44?afluyykFl)<=ZJ0c{04|vUW;P}KYb~p@0gR{)qqfo9V&T=9 zoD++;%LVd=^hJ{1;geR7lrQDVEH}ofyia?sAzw%GOMUW|BrnzE3B}ixT0igQZ>ciz23x-_5eS<($eMPehd4J314@#@5#E=-GS2>y~_ulC#tabF?G zd%4bNkGl@A|Dk2rcniU5hbw~7ENrBTu>O5u)iHuqhhGHlllyw zn%jV=@3NUvU%!%Xk*+uBusofPRT(^0Ky5TDP35=Z+a&&VgS0m%vlQ*x0^Y5`T&}kq+J#x1*X?(Z*ot(Z%yFTCx@RY}vLc;zB8;&W@qpP3qx3 zwOQ^O|NMg3Ucj2B$kSF8a7zuw8cxQCVvG;chC0r2KLsl+w4jVZ;NiOt{7+Y;z(zX9 zEuUQ5i%%PPVOKp?6_VzQ;>!hiR4~njn4s$Nf-KwO5RAr!jsQZ%AXWll3Gwz>CXpHT zHnIcwAQEeu9O~s>QZIyDnjm{Ip)R+6)9AtP;RCjZxkG`%7x(lcR$->7_d}ne))1(` zBp-x(po&{C5LuWCFpi0hRPaLFPU8{vsmAv~b;f-VxcJHja7^V%)gR=xF24f|6ts}K z)aCXusvP02K7h&I(}iKM!mTJGlIP4BS!Xv8d72g}D2R;G0?HGaJZocQ;dp;i&OfAf!u4; z9Dc5REjJAgW*qLW)QoHm**%QIZiGU2m*b|4%lyVEWWwIIsL~~$;$9sn8PtIT=zLxG zV2)Ge$`t#_#j@xTegRJTqbxX3i03w^y2*iZVz>(V;UiD2+_FsxTD4PMeox3R=t94s z!fddJSr>aQHUJ>&DAC;d?N&(TUkVB3l#PrYu#*0^fpXoP24Xxr@$<~mKw6_2I4>o; zxRGYkWMv~&qTC(q)le&Tmix=^UhUwgP<=ucohmwNa1Hv|S?-6xBk?2gWfVY3Hh8-u&2 zBe{kVZrx0da3gpAZzCLRWN+yjpzhxxy+;P$CZSQ0XEE%iW2)nSs?ANXlF4B<37rwS z8&d+qqu_-B)IGQU4eU3SWXRYlqLM>-?j(#=Omoef1-tQDtZKxGZ%_0^($FV?22wd4 z1G_Q?d$!v{V>v?rdq)iR95+#8#{sKeEDp*&&qZq3MyKk*7~D8_J8|Hd9RojKMl>_& zsVib|=JrJM!&%PHO-wOgej^Vr$;Q64B__t6YiUkoRMC<7WYRf(VUI7DeQvm40U=3CQT(= zXEqo{%{>Q`?&!M6c0()4iG!b`0l0p~q-Wd9o|3kE#)80duLPS*xZgHI&H45~z11OV zbvUk2+&3DjmP*@GtOp4hAVSjBa3e$votpnJI+9!h#ba^TqCOl?BHIE6M6a=ip{7W7 zmRMQ8V53teJDN5%e+6Z={DaMqqI&;FS={=7IrT)BDwjmNyZnKV!x%67Z$P$=g{%#b zdEamq%(K8q5;YF4D0R6zV3$~DNX>th!ub79cv?|W&>b4oIkBX_v0p-Lop~de+fhq6 z8WN<)H)71kO|mzUVG3A^UvO~0;4#T8^(PvT3(9o$cq|dW(%``vZADwc}0c`O=s=>@p=s$XN3$wI8Gog9UAGPt6z92B7@mfitDq zv-*aNi#4{vaFCkM(~0g)A~jFlGX_d?L(UY~)%6)$0Kq>1gb5vZTdh9P2uEG#B`Z4Z!-jH?)6da94Em!d;qANEV`@u@US-j99&hmc`IP`iN|hun%;!qmmu zw};rI&M!f3+*=ABz9J-%4@L_fup=XeqE^)4Cg2e-FdZmG9_1A&=&J)o;((pzEiCed zw5E_D6f#eLV(mDn;iKCS-A!~z0n`{=peX_!r%J}4BOIiBJ2LM5h02dpM~?+bH!awR zkURWdGx(inp!|cJ*HHGNr29b$4fAx(1#}BQsP*YI^oeHamYOf9>wz+cj$)9jLr2k5 zP>e%+Zx#EY?-i({1W&2?nJl)KE>@D?`hYN3pY@~D&6FnX(4UmQ{p_`aX!PWJw&?}^ z70^~A7mkj~pmSpFhzrnxNKXY=^8I)+Q%Z7kWb>7?r;ppyVXRlj!NNIzob5I|-5(zu{jQq`|@Rrv!|mAl{mK&BB=xg}mj z>|dTHxz~L2wR2ylPZ(*o+qPpt898+e$wV zgY;DVwmZOa$bj_?Pi+IlH^~<7GA!O#za4SmnoBA2d?A5u2(uvrKJDo zjTDK9u+Cwh65lq&LfR!*Xhnr3F~zTn$(lz#-Rx z!X?cFmyN^1boAhzwy>7qL>{IZ45hy@*=rHJ9O~p-c;d0nJ&{VFS`foCwPM#yd`Ac4 z7uJ(k6>vTIGp4rx=~7{iCLF+xMNtMvm+Yxca-HR75dnf(OOQUL+cpUu7kRk8IxsfU zwCSVg-63}Y>a}DptB%G@Va0RnaRdvu!zG6XxmTek=4v={VQK{l8i4mU5s%T_yR?b3 z{SpyWT1DCXv<}6Ziv@Ag!yoX(L#U=Etg^L1P2!7#+Rz7#HY43yL<0wF6E)h5bgO{3 zS4c5a@ifYp7=U^QLIP{A)vy;wB`U%f@o2B)P_A15IWU=4UTes)$*&5m9~-f-vv4Iv zqJi5$n`Y}KFG`y?p1mWYgNiH7M@Q45W;V;& zg6%))^bL+*NXLZ^0Q+}#p=QX&&E1MdOv8Ci8sOTboPkx5=DE(puR3?w+)^NflM-Jv zVu}tfPj_~dmZ9Z(Ubvc}6K!QJC&gOdf#=;%glV+tF2CVv8qE&^xqcXc>IM9w9s}u3 zV02%{l1xf4-cuHJigB+!QOkYQe0rdK%&450+qsUDiHS>I$^R6hV93$g1-n{h!Ox)` zVhSD&PtZ)X4eTMp=SL<(zs3rPm9T>Pw zu=dm5o|^w8HFyUrHS6#JSNFPTs(jegUFMVNPi30=tTjHLn*S7~UC(u&UU&OT3+buS ziT=)S3cH)0WUE?B?GeXg^T7QO!c85w(_}iWUk4|wcgmj?WV$*@S69!yjF$T0I;o)X zZUX^84a!*ylScA`bnkK126OUtJrv~$g!}N+l{-i9F`|!V*_dsiJYT3N#9g%w%gJLo zvIazr8oA%WU%kL!Qg4nJv|A=Sayc(zH#XP;Gt&m9ow@iodTNvS`BsNYiJ5#D4=4ov zL660$@*zt16|C+W_XlOJ+WUkiSm=|9PMMI&G0^viPf2zK$lwpA6?um$=o;$C@_+W| z>nxR-^sEIXfp9L$X<%qy!G>^4m9=&?z6Mo6_& zv^RU}OI&5mzZq+^z}#rHSsptWr`W8ENHYWI?5dfe#-y8>H#MJ^`ns3K6kt}^f1we- z=HMO`!;p#j*EMH1*l;pAV7}!yj=cf09-hEXsORdx5YAJV?gt2X{pwP9Bs;cFGqQq` zAJvjc7zE$u7Z{1N8I@Q$#rh>G9UL{VysX<#i&2HTM>+({=tW0NO4ccOfr9nYnYfW5~%sc-)8b4g-PhFmtOd9WXv!U()@F zWtgE0WZaE;{)_4yPa%)U$`1jSzOr9REBlSQ$g=rfppEZf;ElrgOav4%>=YJ=2(S#H z#L0%GJ_|tvW)~sF$J4ygN2msYO3raL40It5Vb_0bi&I(DS6sCjO<>1>COJfZ0`z~c z{Apx)!mu<@eygXvP~8ZsgO!iXm3J>0LTmju)hXn$5UyqMA`WLx=HU@dB5by+#0EL( z|3x-$L1*lReLZ)b9zkyt#~OGcw%_HUB_ZKMi#}aX&5Vw zM!QK;4UkFHR7RKNlB3V~|K-P^om*tEY{B>1N>9mwa+Oj|Z) zz;m>QWn8KU{n1zQU3B>L!0AH1BLr=G%Bb^fo31jZIvenwMgbT^N9x2giU9<%$@B$O6;54-XB@}{O# zsaUKIizR6tS;-B164*}7AL%(8qfPSE-Ee*E5TvO&=b{e?ysXyAQ!_05Y72*5Y}=Y1B~<(EEO~LiHV`^8yHP(B8|-47{|Dc_eYW0 z*$9qkPM?vO0JT`R73;x~CDS`v!OA~qa|wkKtDq9~Xd?ghSjn)Qj-n{&4r+?Y!JE7dxd zHS%Y?OleC8wv)P}Z@}qhCWj`tVZHK~CIqagBTNJdBBV~69KJ?s1>gB z8~HMK0>tJKxzfsysqSR=L`%SmBJBWn!BQx+n?%t`$yC|d%t&ZhOnz{y9S3dUTw>sf(c?CtWmeoam=RNJ=6E=j? z)J{C{-#(ycw{fRVhG{F3F1vu^*dDn4|8*SGYi%CJ$WkXggETW{CAv5dWi|;-kE}L( zfz13=B&{qqmp`9#45}FuieSk_DFfB7D`KUX#M0%^JVw?eE2~+fvhru4^+U&~C$+eA zt5jA;9vq{B#mLxzi5cA$6X?=;;Zzl#hcINuCaF{3& zzjcLQxzSX3($S{EHqFH~rulZ@u_{R`$??E!M)RxJ?o_QthE~I~D?XY?>^U(?1}eCS z*nenjPD~XR6Vp{I8e4@W#3X7AtAP2sOcfqF%2dH-S^`x#S`B}?VY4l#NFEvV z?QAS5xvmB5ehn@8Gj`1ch?(h+&R!#qY*X!p^iC7jn`P%Qi$}e5oj{Flm5yYux5oEa0bqm z?qtoIg$C8Wb*WV)#j2tk2K_A0qE7t+pKiE(Dtfzot`Na7(&E^zK$IFYQ80syyms!E zO&pt-a_wVGA6$cUgM0-y{ zkYh(KznH)q00=(vXf=OT=Iz@Zv*;k}Wksd`?7$L1ZeK zAq26Th-4r*3Sir+Il5qa?#A6svBQMN3_K?4$4nlOQYj#{SqfbUzo?~4mt+#Zutr3t zn&%<7iRmsih%9xjhmZp)bAix79-73Y88_CZBFKqL$LbS1faw@b?KRL)sF|;uQ8Uw5 zGfULu*Vt@WplA0#*{P(;`>0J@qfNTn;~{<|;&8$A>&@RM-z*D6a=p*C6CJ%8G5j%l6*g8@yA|z96%#iRtIJ_Z2$|~?g%6Aawcx9dE zAta3`Us!A0ua`7lR(`N7t}LVqah}+dS%nU!3hAh?9dVh4^iMBwk0rT;ITkM1GX8Qh z;(>gm)tFqXi)^uGDQpSGC>O_&3M3PD740@%gZDsj7NPO_JlCja#n>^7*u!pg0?;5bwi*GcA;$ zn9JuzfelAu@rf!m2Co;FvPh}LyS98oN#0*#$jB*3Hk!G>G7~Q5M$|s7kpX@56+7T^ zalquML?mjVnF1G0nubx-G*qqN<%?`w-Pr1h?s4j>7;6YHUY#EUq^U#A)XM_Yp{2G? zsHJ+MAthQwY#E0U&sxM#^HtF}^%X{pgAj3wU$8w09Iq~J3=BbPNn>K-f#6PV13{@O zA)ux#ML}37qqMD$srjrxdD74u6*9l#w`iO+#ls}*ziCQ;aGA*mg$$Wb@o!AXd|V>eka{95sL-) zc_bM_Xv=gp+e0)V;sGMC7SB-s@(@WxlmP+XY}89zaklrpG+TQqV^aw|m{Foz{);01 z#x3P*Y`$CCs+HBn+uG`YZ3o?3>e7RnxyXak$m!~L4Hp-tKzE7kX*VO z24qjMrVZiMOXQb4?miTIhvkM@lM(MjK&@~0Pak>z$Mu1LCb3YMJa3bDe0GJdi#a^SntO?qMZBV%U_l(|87585HvLK$&**IZ`c zFml%R$X$lM)GIA#N>wv911ckC^NwtJEu2Mugx2Y5RFEI5KZOtP7}FeA1%2qM=)W@7O_OD>jAY8f3aA@LX^ zv%g3iEPrw1E=Lj^pX4m(OaCVsGK}8gl2ox_{$K45Hmo(7CBmR!EbrluA@3p<6Vz)!jnk*^?d~r2wXY`EBB1Cnmh;<3EvKO8 z`JC9t6NAs>Jr;FZ`ZW}BK?4y_dLjg!wxBEPMaz#=H7HqF?G`X26Rf(uWa?Ga~ zZ>18OmE2>I$**a7P2ya;G6RU#LcaiuYXNz5E84KEU{?RU>%;B|E@~=gb{h;}?1l zQ9petC>-S(S?!}167_GQd`E7pJ+g*le_+2om4Q#S+RWaGMGS9auK^{_1-M*?LS{__ z+qyVZG`u7`k|Q%mT}cN9Th;0|!^Ky=Yj7&9k4yp`ffk`xH$bQ6%ePq0hGOnlbY5Th zB_$U{F874v>WymkJ^Kq(vcg$*V(}nbcIyVhS$30Ruk0TiaHr-!Mx)f=%Px_tBLB)4 z6TN|7;=s?ffuDY`*mL%eCb@sf|g#I8Bo(X$`+5m}bwIwEehh@!h9cd?p&Tk|-9 zI|K#83$l2QbXY8Y74cnxhcB3QvGE1Erke;1ItzA2@X-@F0tmZ{Cu>(+Ln8UOOkn;R z0CfWB?R)$V;eL%-mg{})dpNUseJEUDD_sD3ZADIC%_S}3psRhO{8$9N7msY7pfUq0 zLJy9kPWjX%QOXRen<(NZY#s!hd?HjaYMB4>-RO!WqW{ya4R3987kXoj_nW2*9e;GFC>aNcRTIc?FNjg&12T7J#W-6)jhScql0PK!z-~e2*i}s?VqUeF86$6Y z`iOKNl8)O$_2{ljEo8ym^76?(CfPGu+#r_a4-Gc!gbfEq+^ZzwHgl-3O$Qqs19Qo5 z8N-|h!9f$>NzNoQ#A}b+L;BZ1536S4MlU#2_*vM(spM84t}Esk=avM%YP^>m zcS;Fa@ZZG~jr$aAg%F9Zn1sQ|yE1YexD$#emrN2liN(*B9O2veOUgN2mz;(ArdzIT za3vLIl^h{lO^SP$eCKn0MXq)}mqcYxL(n?S^7;#Dc719E%9k!?XvX%epJZ2&9 zF-!9;|23JP1hY&`6a6u+M#*WPbECIiWA3f#c#L<0rVo+*^X3N8F|4Ixy z6|<+q;8^0V^cDYx(k_HF^g1P9yT^C}b?9{*PcGNe$3nWd6)}3sj>O!uubX0XjzNr#>vxpe9#Zw_qE?~BWoUWAFS(91yLbJUM(FJ`$`^{B(2N;y_UR|HL!E&l zFb(p3fP5Kj?gxcGT|9QLH(eZ!F;ox|I#u|H`;k5pgoN6KKH@x!kO}4jA90mM$UHLK zM?`HIGV}ED5t}TB1Y2o7A`Yu>cR1R?ujtRTP}OGu1!e~aEV_>f`e~qTxa7{_d=SjX zj7-Z@%Pa6=zhw0WW0tk6SCj%=rNPCkt_^T-#}uq#uPBeR#1BnV0*BNiC`i?;r~Ydl^+SUc^#%`XalZWj+cMa)EVaYDfrjYp@Sd5 z_C31J5om9|k@$2quzE`x-*bz_{fro2triUj$zRurN(R)b8F1 zVv)piVR5sH+H2yuAP#jW+fYzN3gCTt<1oG06x!KLN~fz7#JD2sNCvx92(y-_qg*b= z+Q`v4|K_K5EF)cgjyenTK0F{uL`W{S7%2VHJL6-d>fXeT=^e;}!U0p_6r`|!L4{9H zdoUbv>j+v!F-)gn*ha*44cqC$oni^5Zq7uwjDK0tVpLh(AzWy5yETHd9yl{w(eAYK z7-Y7_%!qRsGBGS}7*AluiUceOTSXA34bbAu zsrzr8-cDDmFhFWUKaQtJuDaw?T`4tAKhzoBb5J8q$P$6o@xIuRux7~x=I{VHZo z;27dhH=d`%UpG^Wr#=!bFmig+i}&EqE6|f;t2ggp>*_enlrcrZBvTAs$&5Dg1V>!S zU}7o?i429^7Zyqwnd7XhP4Hi-g)Z+IXJBSl_5)1*(4hWGM+Om?q{U&)iIFa&Jv7O z8KEYsBgqDWY%ww2O1g+No?I+Gq(s{&Bb2Q6p*th6-p?j@{sY!Cs**os72s3;wv762 zzpYl9Ize~qIt4A?f@S4u;O&rypI_oFaP>x$XKLS+8|I+%YZULpbYVFDX07fghr?lGX?Nh`Gi3s=pYqm z^CYQhQ1Y#U^EHa8DW+o$>PQwmRHJalPd;W+>++^~77>1X0OOXe_{&jt5SqY!4L{KF z;)_3XDhKq^h$#@@K1D=nv=+Qhcrhx0fQKNn2Ik0Dhwf5872O4|+l>$e1R;N+G2a>t zM?X^jna7;Q1eII*yUA&sL~WP6=WUv~gLIi;DYG@=Bd78L4AfM%HI+@*c%I*N!Y_$V zk9LGk6(ei%)SFm;b8fCto8cWCJ8RH=;zNn*8%!Fi2xz#%v;sD$e)Umb2y+^>XbLUd z7yC<~^UcvusXfA<`Q7T1sj31p%Iq#F|ry zYcb*?Z2+7nz(rtlDi@NO*;oxOWI6`+zVIh0z6J^v9;X)2`m{N$)#mD$Ky&h|AQY#T zFAm&~;9KzxyGWd>m4CoedsV|`k#7rJ%|N{(>DDu(7oz*}%sejfxt7)+3nZ=oF?&8+ zI$kAXKyvqCc@DGR;DoR1Lj7BJlUtRW@<0T<;WPAP_iasckrQ5rC#Ui`{DleMfL@p$7v>~J=C=yk_qL8}~A2n*~aCs3jKDrjB}&1a_O%a;fi zVs*kK>_iqfLKnA2it8`hoR&eSS1KMgb9)kB7QMs?JA!P6zp@ay*a^=~rFIUap~wfW zY-qzU&D0NtiD$Y0?jw@^S-jGzJQBT!MZ5qfa;u0ajeaI7BzK_9_&=y3F8oz4l*B(5 z{2+zYk3u0#c-5&W?C;LjtgD4}i#X8@5Dj&Hh8G|snWxT!bGs8rR~DV@gjc}FoXQR8 zw{DJRmPAo_AbvQN{Rl$P0*fi8sql=zpei9xRYQS1bvuQnX<_)3%P>q6P9;zCL0LnK zDD)Aby^OSb;OD5@BckBx*h+CK-@r5LUPkk7CcZ2>#0kIBOpuVJCb6>E4+sin8@GW( z{L9DN>1uPd@NFWTM<1O^eqd4c`V0Q|-u3uP$$zTm=dQ66z7Yvnj5vq})gDBOjg^0= z&wma1lQsV`;cwfU{3qdW|zYOtvZ^SaQEdt$Y zR`fI!6ggBK3vwFm3@nJW<6j^UF-AFNco`y4Y!Mg*cr~YeytIkp(EwXS$5HsAX2qwArXqnaUtbh}S+6vPxXnH+zh-r$(%gq7H#+aD;M zG35xX*O8cUDyKq*=6%TLeFLGCTcvp?IN=xIASG)x)r~&Y`=q*0Q(fqUZJlP-Vj0)N~` zwW!OS@a=eVD(CUHlz$;qp;VV<5iL9dP0BJtOA4-SeD2Jzi#7tF+U%^&ON%J7()b|pDe;@{XyeCENCP)-r zO|mg_#3@JxZ;0kh=MLXG#Q0<2YX=#^{=42yHs*U4DC|3k-fH{nY zYbh{}#J}S-g*!nDJlP57;>oETfxpsCvjLG2u_Z!Fao7${_%0cWx|4@hz#lYQ3kWm9 zf5#lA9)?`Ch{EGYSQ_0W)pw=(U*K!n@fUt0%<3)> z<*9SP@4l}|Ulq~~Lb{_B+JaHfMgc~elb=_^iQUB#s*+_51)4E#qdEVLpovLDhyIpsnv$6O5JCunu5x<2r2_TYmEj)_}~CSSA2dJ4uO|qYtTU_;o0p- z)ytxzo$yxa*3tdot4Ml8w(IR}9(H310arU9=Liy)BO(6xI%i>Ti2oc}FSQFb!t;H| zT7h^xiS1osDHyvS?;$02al$oXl(p!k+8z_h-2;EzGSZYrtHgE_#epUhBz^B6pg^oZ zLw$!K-aS_nZx-Sr2}I?zz7VJS#5@e?_R*!E;e^}a32}}mwifzQ=6zVeL42r%O56&D zXojeJQt@GEe?IH}FT|ol2x8R~{C3~cq(hzXi+FM>S9|2;KKY**AJmB?U!=(|b;7p_ zdAUb^4$v|TFv7*=ZdDxqLuwXJ33vjE+tXEyTgRilVdbALjR}w2zW@Oe9$%A$n5g)5 z>lYy17E9V?jU~O7q+>v;9z^C3k@N!m<3_uqz|ts>t~lXql3A~h0di{zFN>aqXcw+t z(o-p2N3{IeZ~%0ZP;<4B($1uqRhs;4C;T9uoXUIfS3U2s@CX%ITBzH|(uFKDHOo1O zFi>l!as_5~b(6>PowO`Vxd1G%iCM4CWi@Vl4e|=IAa5w;y~)h(5nA4jnEyqEw)l%O z)vcg)57Ee8PWVp*GN@P|r}D(kuzFiOcXPrcenS~$(Vk8vS2fbJ2=`J`vO7{M6#iRk zJ>V?ZWEPKE3KdM>Pr?Qm4#Ux`vrv~DW92k+-j@~ zAvMhjKPTSG0~uQ69H7~>1=S#XLX#bW08$o`TQr&Vl46$Zx$-7jbQ71lf!1z4!?w1d zR{|}qE!|x}x03^{9GMD*5WK#^zFWz6x@_>8h-atrPr#v={C^c!yXxg_!Qx+M@h3MZ z{?1}syr2i#;?cbBOB|f=@sHwrOJ@6mxrn|jM({QYj%+M=G*%Hxy~Dc~YEk6w{egxh>5WyA5b5cJ9b!_;(p3$Ion4U$jgO zW&#o^smNglUN0H+W!!^PT`ZEb793xM2y;;a4qs?NxciZMpGV{WQ($o77LxK&uS3nq zXaFTUm0_?mgrT>zmRU=#*bc&8Dv5eZT)zy>s^<8$Y{^=_@i}VQpNYNF=v^|GU4ZP8 zQ+ZcAThUrjP@DTm-fWXd+saH?s`~8}jaq>KjM3O4{C0PxiGDqrJoX{iN9 zQXV8hB4)&2_kdvq2}+~)O6m6q&+Q)1KMhY8!xOJwBhL+*=Q-iIRCp$MJV$^BcBwH( z?5mLT$Wt%947L%PjW;wp;b#zWAPt9TPph{d8NdMBEMc2XwicT0MPYmCTe$l~oR-r0 zehsC~ay-2ksuLjZCYgAZKm zgzFZOeG^3u25^x8rwZ^&0($|t*c5mn0Sv7l6sqY69h}O=5&|oAU>7HyxwH)1LiA9* zV^rABS!LeHD&#UZj7M;aLpSD5!iuD)2(VY2rqD{Dx(7fUqe&T6(KU?6;7zBg`Td(> z)H!m4pK#vNUh1`8l*1JaP_8Fv#E=gO@P1G@m3QN>7;>qpS0$2SV#p;zm8uQNDXOft zJ3AWGVP|m4X=&Y-{ZL(iYa?gC9^@-7Dw%3J#%o(4uK;iHOEaAu2rsw~>s z39rJFQ@LFCF*^V)L<#x0UWIdy$`rq^Lk{(BFuS*sv^4q@%5cI{h5Jg)jWJ~?7|o#j zgQ!lniDWxVv#k)e6NT+K&1MVj$*PMjaR+G!luQHMhxvn{exgbj%}skh&W-(`S1ceP z=oR#xQUHxtT!+V4uNXyhbX@Oy#VSUPrO{_Z!!an=o1_LcLbU^b^KnR`M9qO7d8##x>~7I? zj|<&Op?i`bso{;FW3yj^^qM*jKiq}H;UKURE*ILF_{*sLSdmzTO1ecPDUI?xjT4?I zRO9eh`bwn$bMdp}6Er2Pkd~)@h4ehN?j_XIpM!fy(Hw`=(k&=`Er>u~3&|8>SIB4V zf)AS&@^C!6`;oo_%@a~kEq*waldvMy^;yn(+)7E(t;DM~AQi-S-m26yud%i$vP!-1 zIz&CCMSUcq?iNw!U_~W^*&PC$CBPd@IQ8rY8 z9XNZYt$M%Vpnz!{i^#~)OZ~&RTeFA!jH)+ehL0cfHTtxCt|Y)i{vK8mbw-< zQq{q_7E45dCF%x9l?s;D2tpD2yD8Tm?Ac4y5nxdtGBNlr|GbGm z?h#s-u~`3!E^Vm`R|aF8a0;GFc1xRTJ$@wHD*S;ptsY~2J;ns}C~Tm|O#C)_G^HMA zP*yJgoQyy2V~njzqYRdva3y{?m2_=!=a=!oNwr?j)^_x|41A`EzCvVb60+&jmXj?2))X(ctY!vA~cf97xcfuFDh&w_YIhe@IQ#V7nG^JL$XORDS@~JNUEoh`Anb0mF*G=TwgNz4s4Ha)LIff<9l@i;=mbfa&JA%BYkawBp zoq~ico}9|t_}d?)ZuGfYD1NF_rIG7e&Gj!Q+zJ{Y34viFz%|n6YNbAcbEuskg6l-h zb+r@Dl(G)RU+H~UI^p&LNyA^(U<=6e)L0lPAoY6yP3>E#Qc5kS)Gy&=sQp#NFO)1L z?>ymcAIrO1c+oR!Lao$Dx~q<*P9M`?ZatoWhI8v-0GheA6CPvd);f+Z8&>;s>p5DX z0w;W#7^g1?sMtPa^6(BNY!j$dC%;my)KhR>^$f_|L$r)*kpF4HX4#Lw;6l`~Rq}!G zyqb`sZUlq7m$=gCEa@HHerJ1Z1xUI~sQ^0*@Npyp0wphjAT<$xIHWMWyF`5sWkMMc ztukOfb>|C$lvPK9Dn}J%q^rTUeF6$LeRxWhShLosP=q5a9P^Ot`gAP@M7>qE1ZIC5 zKMhYe@UY+Sc^1XIjI$W(MgDmXf86%EIyZ^t^^%kQ6@O(sDg%(?(PYLdGR+9zLhx~# zQI-0^REGyDV0hLn{bjH0^{;sPvW$Sf17h{<=IeVEcvO3;cnJTrz#sQ2CSf}z9tZH#6YA(x?wZ6*AQ|FQ`DTJH* zz@`dlo3WbrIOIz8(+N)HF?a&+XrK4EJk?3_Ca7b{dklHolcO{`R}Am~8X9Rbgk3Og zYtd7wy>wIR8Am<8q%V|4*9!eRLca}v5k>Dt<%F(gC+J=#U0JlL6Mj;NUO}QC`fLCZ zd*^%#O@h}h2eEn*MY&G@<3&*wi3yyh)W1{9rR@YPfMVdGjXBcFGy9N3{=ZQ4% z9Ta&UMGn?fEsEbSIa&8-9x*_ZzKTN!fhN8D5v|p4a0xbA6>=8pZl?H7p{(YV^(}WQ z%A&2D@D!|GoXT>P$eLu$)QJ$ZkOb%*bU~HiHjAg@*P~Jj{+e;- zby}z2!6<6rTx1ciGmlLkl&pXbyfB+*jM8EVbedoy2{JW-%Fw5+YgE5=R;mv>60iv0 zl%q*z^g@+4GYtgQ?t#;(x*AiJ%6IVVDbx;`b{TKSflQ}>HUa8R=S)`?ZRvz3;mN6- zsAoP5%tx{=6-mFI7SoW6mg-Ulq7*jd{cQUJgL=oQk5>wGtJmlAL_{wI~moNz!4(PN-bgC z1tN5zN&ut!gq8jXe_Rfg(0!^CK1>G9?))uwt|QGm_`~|3iVD2}m5t+#dvfpIu(7P- zP+L3$uVSyb!%>_nVhJB1?TQkLoG_EmB{^``oq%IVZlbEuW7RvTyt_(MO)GxispMxG zq49H|qCd=mD4||T>W4^Orm3%U!dK(Tsl0-}MeF0Ka79v++?YmxVu==Yq8On@CA4F>ooWuJ3MlU`~Hb|CZAG?bmE5-4d6Im@CWop2tK7A2ivpLJTZ z_G%@2|1&7vySCdF_DJe#3 ziqoC&Ks=S4As(IUg!zR9r?RV-e4OU%sQQzyANg8pzSD}UOR6Bbt)}R#Qc2N_6p=)! z%P1%O5uTjNckvgLUn4IHOLtPW?Ap7)=Wf)LeVy>r`sqlg@?lN=5~y{TQhkxCgMVSp z=%OAW@5AJsO^(v&0yv`+rq4T-`DBe(r7S2u)KyI*@pU8~r-|0ce=hNxWOE1GC#7=(( zlsAIX{gm-tY4mO>`gQzpD!D(a1>R191u+7Dq(UO_x92>8t<>QZ*p~vsT41>dEE0jd zz5<2bLP6-G@V68W>!A#kQjK$P*V*ljHW>KbJC{*zwK@ilhZKP7kAGp@R_avFUjwxG zM@4*l5uZko7~u0aKpLmIqad08BsHeg*JyS$ZCjND391Qd;C{&=u{8P^#PHN#+IOIc zS6_mkz4=AW&|1CE5#l{o>v_$vT*_Sqa;Gx=8;Vt{3{yFo5<~6OVlwe9B6pT%dQzCK z5YOeOYEV+KVLDTn)J}!SbOo9C)k3KDjxZe~Oh*tTHLORKP{SdtDAF@ED$TY+jq0FV zSZza=leOT^2&&yqwW92nl>I$~!grFL@W&Ki`2qf-3ip5m|I9axrfauTA7E+#{4Rml zq1@qcbeGkEf-5N@e5c5%pqx1M7`1B&j+t8ENk-rmT9cNloO8{UV7^(HFZv0CNo&ww zNydawcXcTVMuA`s2#N<|q={E~rWt!`Dc#jj5*-erTS(MaB=pk~GW2won$JeuoHR9#n$-*-5Y4TW9MFvaxhL`I0CD?d9#?`Kp22iwi77mn@0tCl15S! z7?vN>oJj23#QLv>@LV$gPZd4Et5DkgIub)aK0H2I|J-MOo~M6C%+DPCbF=w5SpR%b z|Ab=e@r0A4kaw>Kd)$M~Ffe{>5c&T@r9^NMuDQwxGj|!`YH@TUnI3Q~W03if`>~*( z;L)E2dYn{``X|+=vaY`%?6luc;hlf$k-CXORzqQvAS_Kp;PZ*z3;fe4Vl_mV7Y=S+ z%~@w103iRohrI6}AfHb1a-aMfA)iNbmK_Gu11C!b^VE7k)vDLo5+m!>GW~#~yKspN z_yFIJs8iz}2R>HebW?lz2yI1D7rdZ>a~Nt$95iFc`W~rQNlqg4T?NNQN32tquQV#G zg9`31WErGxN|eHD8x&A$3it{p zr@DQ3`tu=Z*hc+=fAU9+0N@)wZNv7o+RdlL*-v;Cg}}E^YguW5Frla|;L} z+hZ|C)_Y`x`Kps`C(8Jo zzjzT~MY|92h?_4m^tBu~TA%b>ot`vC|0$|{JA?$SF)hvq`QtI<`b=C|t&B+>M7`?_ zclu8VXzFoK#wW1eTFm7uQ33=^wgUR_@{naH?__X5nLHo|;}Oba!$d&zGom*CAr}hv z;Wu~DSg0HuYaEVj&PW_Jw>nQXZz6U4{d+A4a+idfAW&VBr)~<_xM~ElSMJLX2<7J; zTVP&HLm408Ni1RR=mco9fZ||dtmW}?bp{4pdt4sqPfsKV&yz1v%YG4YZ)gzQC81F+ zH3d_c;+@Jk>w`0akaCeJME!z^6&6~8%g9y&{tpdDk$A~)6jgShGCqI(%I~Pi+>r}G zyAamoi&isRNh0UI8aU3;0*$9qQ3ZloP7s;RYmrH67nDv zy%9xYK_VaqYf!*o4QMbZ=o3Y0)^#yH%c3T(B@$v11(RnG%i2)vtQ8xw`cncZU|R!N z09)*Hd8kn=kz)Se@0po9_a?#J{qKGx@1Aq!oHJ+6oar;1b3<0KALl$~7pLMY(5Iye z84$=TDh@xMvjc@X-AqZ>Nxh9v^{j?nX(azcM9f#cGJN%a#*Q(PFVK?b z8_9g`1Cr0CKv@8usL1ThIt{sTTV`luyMoN1O8YhsccI(tEqkUZe zMLQzGFYrHwH?swdm!x5Ypn81phdZup?iDY?s!}e`GNY!U-df%a@2GT^Xm8XhP9vf} z#tT_UpAC8>B_ggamc&x>_K3FVB7uX$TK^QPqU``aSd1l~HZ%u;rgc8;uJ(J~7*{yl zKn^=N4zT3ew32QO>80+jtWxZviGAZU_;TB=kC6#&wnzCWul`#0s*s!EOvTF!fyndf zIKxtLG!c6du}CAZjqFbR^6DSvH;@<$;LboK6IMqmI`ndi6({M16_l!=gwuru_1X!vx%(J$P>%UE3RgWVfap64e5Pw(@zN@g@lv<(vKUv zs#(H-<`Oy<(B8Z>l8_ui3IQ3->&^%nK*)iB9Lrl72*D1!wA3DebT02vA?`VX5M11d zKmI+NSo4i{@Q#FN>uW&oc-i{JC;GzM9 zXx^+#MU$}u4>65Nmt#e>72vgk)qmeaAFCt3QLBAwu^oA%7g!iqTx;<=lVKo!14-7m zFux7RZyUr)K`d;KSSX13?Gg70VqOH1qKxZ-K`t8}kcdtRSN17sN0@M9nXVTtP(5|088|0iwP61+{@=fOaJ#sFg&8%`ecU zfNJw6dRvb(rGUw&H2-d<>bMjHe~sqqNpr3}SB%g7VefZP{9J_dFVY;@QX)(oP}Wsf z_jDKm_v)}YzgH`3B1TsxIy91~w^zeR#5nXUXVWtgw`C^x!n^OW@Uq+bhh-_(70L!#e*(O z=)`DWLx@_nCo_1OXo<0FoBkLV*c_?6zqFqwEr9f9USgE39!1R4?Zh1Z3gxOVd2ia- zCRZH4Wf=WC&>FcZWxtsjfqwnSV*z>a!ne3;g?y7G*QVjhyeg<_=5COhg&QlI3O2d= zqYEs52w9y^R>_()^qA1=mcW&xj=2Y+!vNJ(URF1=hEH!wdd#Ha<{vIbtL)<>#6Yc~ z)}wH&TPvf9Hl=z_V()L;g?r0UEi=o z?osh~{S%2oz=K`w^Om7Tw3o<-VR(CIowQD6Ny4(oS0HQi$5W9JiN8#Bkx*|KNvhXG#cO z06}{b##HODwwXdFxQHzOL6+Wv8hQ>pI>9v7iE~)Pf|(bDj$qoi%@{gcy-g-T5S~E3 z`w@gw^=Lq3GP!6LeEM*hPmj|a^+Zx{#hN?9zjPj?HVE_wK+&cLjCn1Vzlx-maascR z-|=~?+M-!7o4sl}u0E%D%%8ypcq?%(q+)vb#33e6dT@_CVH1rFho&Vfp^%HUKBoC& zb0pxg0=B*61Sxr6NT}iRY8cF^Q?!5oSR~~oOxcy7U`9pSG2C6omZB6rnc6Y>dqF9ze`6aj?^uj$xj)R^S+Qs2SK1W2(+*m$qd7|S`MwK1NZl*(qx1I z^O8B{W}zJ(4;ukbQPU$Cx`sjuB0BDYbCNPDdK&RC)h)3PxlTbf@L%GXF48D^g_cipVV76`_I78%YCAgEgqt0UP7}{Cd=N-wLE$9`b9T1_l4orK52HQfp#Se20d*ui-0kKl%t}OdE z$$ohxQSY)|RAVI6FiGx3lGIzM#d$=mM~3-#?}(nO$!J=H5j>224PE{}y7Fg_7JX@3 z{-)#k0T~=A4BD1Ia-S%INR)#i{*c7kns}=A3ju9a%zj}Gg64FPAe0wg7Aqdqkm^3l zdvJ-n(=-TEx#WGR=AEM%ahlG5UNf4C6RC22FUK`Tw%~8Ic=1UART|k48k)@vBrOna zEt9nr!uvv??NoRk-zY{U5O4v&#`9?BSCG)$Gb_SAX40LQ6mM;qbz1aB!>$%~HbwHU zzXf?P+bmteWbaID>tp{9V|v&BJ6Jlsc!CqtUW^C+Ytq5A{<5Cj{?QS)S3lO=IB{!x zlZ}Hy+>kQOzaqkI1G$arh}+eM8zZ{qc3qeo_@w!H5pLg;+vaaN$mzj`TR5kK!`v`! zgpo1QyV%i8Zclc^Z3CW|pxwf{eUl%`Df-ixp^R|*iQLZWh}%PkTUfU{!ra)k@MW$x zXfu8$w;ej-c4i0Mjt_IA(tb1kaXI~!+?Iabf!%UC$mtfWN}!@>59vZ~4@9`NkXuwyOrJ8`WKxwTz@6?vHaC&gz8$f;(Xa{|?Jr?gSU;oJQvCyjRazW+GXA{SP!UR{lxFz65edg}+z>adXC# z_=RKr{00&Ss?+?3G_tc-H%pM5%SS_dJ!W|Igh0A1AxSn;y8&}ifXUDp3dVxZnNSKl zPp6@cskj+*#|CtrG@UpJIqVx?GBt);f&=I2yPA3WX0DcCh?2!J{`m{BZ*wSAqUW9o z3k4GyW~DXoz#&XGPtwV14_N1VHFwjf?YidPmvA!d24pj3`gVsh`2{+;n^Y6%DTHE* zB_3DzAR&^e_sBqcokKC-g(ec+Qj9wV3?<2@#_2*=3Gqs0T^DHct!0T3M`5BOdJRD2vhe@s556liUag2vY`q+-B z5qXFQ$r^!a$m6GBEt<1?Y76U~@cfCvD&Sd6o+n3nVlFh``TaiV+9UlEW)!@Mvoe&5 z$;)MY9}is;$>Hg!y`-NFdR(D{_cGoVzf1K*fn}E;Ur`K4<%#w*c_u8kTvhZ3)e21o zn(f4cnpkDzP;nC!)SgsmJgJGJR(R4$RGkmfAU87Igm|!9VkF&xtKnP8(p!Lq@<)+9 zv3isETQE}OqMq?L<0ahx?jIv8_0+3g#+4mcAa-WEl7zcyLOZ1NYCh34x#4TuF~-VP zYuRh$Dv@4C@Two7Xgq;R4{fG{bSo(*%jKUjJ8gPhoy9>c-L<58{UJn%5=)#7`&NVzNb5I2#w#A}LpWss8Ku?c?_MkO8hI`L3dc_1r_; zAgk;!XDXrm;Zx?zQij&3N@)SnFU{$P<#4cfEM`#H6A>1N@GZ->OK!VB9~5-5s3AI3 zzmEpQ)B&K3(|W!_wXh$&AF1OI6`gD-1*gP58Yg>p8ZYHmmNN)GBm`bMTbf``zpD{f zM}PnekQ9bB7$Dl_31a)pth)b;f1zHfHdxPa-xd+b7Wp6sAZ~LbsFX5fY)d zDQ-0w1Dn(&$L1fTsE)81S#}UhuoD&M=*h9Wlfcxx*_I_et)mS4(K#yxs zE)q;nl)%KCznG4{Gteo(rXt+?22BFYjN)WX9Hrq3T^(^VsqPSci)KXheTYIwX?Sg@nog>2j;fm`?3gMYu=um*M1{%JQ3QrR&cY*|!46Wmxj55)7P#zZKO(>DM zBY~bksBQ;uHCn!nzj~_RKrSB4tSN@p#kKlRRm;w%#z!pq997|+AQ(7Z1vlZWj&2*S zL>OV-uK?F@E4Yv;cwdN%5Ez8N2x#JOppQ7mzesyOX`w0E2cx;30mC$#30S zX4&!+&~gppWr((jPhkr7@3+P5QKg2@I3TFJU=nmpk0 z!wyoPb(m}{YvRlA^1(+4^7pRM>kgO@hxA0hxnLrykUm(;9P_G>T5_O(rUFda|FpNk0 zFJcO##uZHK2Z3=-+lXYPoFa1$ErcI{u#M-C5>L8?gkg3B?LR4N+XxfPY+wTGJ4>+V z=wBhJY*_AXXRyCRg~S};5wylba9;n0KY~2#49d%jd|JfB{D|s4S?{hDGEJ0#vH)tG zTB5$e_Qptp6cem}Ka|&+Y6fTBj73N{kaQ79aUiKZ;t}$|GuwDa0PBOeECLcc;_@B2 zTqRs`i`zAXhup}t^+=0)E=ITy1x#be9WEtE4AI65HNfDenNtGnI@bT$2wy zC3GB(1)vCd50d|}O30_WuAdO|eK&M5Ir2dl^8lKWv!!-tu5^b&Io+MCo&&2;@gkTB z_znTvg6>VqnFK`&8j49%(Qb-h14uEa4x{GMPn~i5kWnGAdS~7wjBz;uVAsuRi<%H1 zg0}Jm76Z6Lka@s+FEVIdiR@P{nTs;vI%T$cBnJTomE>wEHmh}i((*A4m%m-gjEx(>)_FGs14xi00rpIwdrCRHMx~=MZ?HOQXV7@FUvpe{^8U^s zh#@a-6%rs0N@lBb4KUG^BBjLBkOX5h#?w5qH7(a3^2;0(kx~} za|~%F1dM*fUC>zIBO|(>Au1x#U`>>ZJ~uu?*pbBU3~cMvLR6@&T}_4h?hvUEJP?7> z6RPHSgW8blD@y`KLNR%)0v1I#RcgrDSmsRhrgeIt2>JIomTYuQfi;k&)`j@RTZo6w zLDZW}uI1z!MC@Sgb|VTzZhYRVs- zt>$B;a%HO|IM|iAqqNH!sk~dk=an5!!*s8DAMlc#>N6Uc5*!SR%M^{?n#x=+3x~p+ z$!E6aBhz{_u_nql&p9^CRu6Jv43!svHqFQerU4Y|?ekbeb5v$8p4(t5zD|Q|u3~7XxlLNZ zL@BdJkDsg4-B0=FBVFtKJCG+HejJv?zTFJyjV~5;Y|XzyO~igsU*;@^9Vi}cGRrG9 z{5`eSCcYaH4-u0|)v%NXyUzm0>orH%YL?FQ!zB9bZOOEm8EA6YM~Gdlv1E>uQ_R(| zGS6zm=3^wf2Sm<$FxurNy<+{=bhOKm28|M!E~>c_8RgXA#D$Ve#F*`ZM)*2f29nlN z{f@Z2M0rUW`bMMJd=8Q^k7U>fqhq_|8&|wLI&ok?p_#;0;!Hhx1oA4ubB{+ldI-gBY{+y9nQ%~o9{Kdd%-%V-mnPfN?+#!z*1@;2%H zo6Q(#?1UWV>TqNW&ng|1xYBysEbVD8vv{^bAGkpt67Ck{pf}W$0Ba~;CFN>O8P|yg z)WFQdOQv9^SKYp+tqg+V^&L_fW=a>XxK{sRRUO7IX*UN!{b`_p%aEjXD)#&N*fgwv@@Xz9IR~k0cY! zm%!MknmI8RN+~amE@es#rt@gsei1caC+7!=#}EJwlB}(vj)qt)C&_e8l5K4`wzsvR zpf3hGWJCW&J@}D;S2GX6L2X?tcFLoHYHRq%1-rK?VNb9aQ#+fHL|a6lS%AVKTo6DG z@LXaLA>Uyle?^-_0$mL#66GShb_Y;1vz{ANhT)Uo;jJ%Fjgls+_rMw+eS;@qo15`h zulhk0za~;sJ{9$IseZC12Y({1#s^epGQ_(0(cA42F3TcYCW01TH8=a2Iu{Kq|0IKC zje_x_0fA$wNI)P7J2XMC>BaI%#@0P2aR{lQ(4SPX0f~K$2Jw1DTwFVh15G3C`jb2Yrbq+A4oJ^mTm+ zlMe(7V7Dn9r_o(3EQ0K;uUNglEPbai>QRIgG_BN^o+_3y8@WB3h05rz{DL$`pQ zuKI#uT>Svy5-knSpQz-+5uO5?ZFrh0qCWDa08OfmO!YTOHJ#N}=T4v#bi!QSHn_T^ z&qwVGjZnl*bY5LG=`68cxUMtkjBFzFo|;X**#QG1NUMRK3@pBlT|d<~Q z5I@Zxi05;RCQclw!yMy;zmf|57Y&|Q&6%5as_%-lM)g)|vvsLfy|&MvtIm~MzY)Yv zbpgGiL3zAyfDg<|^iy>(0SrNfQ~g5GuQVgI6UK0w=zK>6YmwGjsx!r%BfLYwTc9TZ zia0ENGUp4XuEPUl`Yv0$507>FyCH##3WGzG1+3cjEWGdz~Kk9Hs%rnd3>gJdP9(Nfqt@>Imf+y zFlIFWHS-z0f}HP6A&-KZy($!_=}rrH7QpnMQOlPOo{9rxRhv-l#td4O>M_Q9aP@F+ zw!ChS5yp5H-{3Y($7-fXjh-PQ=sus0^>>F*@?m@U(fztW;oK>-HqKhmcNOz*``Fb?7wQyHyHUe%>ZOM|n># zaTbt-7m6A-J_=~O21$@v*@Si}8>802xQQ9ZXmnnMY>-y97%rC06V~@Ma5E+bDX@Wb z!vaU|OARwbLpwEjgjX{Nj;x2)WrzvwE9O~}z*d&M$>Y^mK^U3JL)a@}{O>SAY!9c9 z?yJ5a0_G|mmN-J!)mljhW86XAH3825L8k7Ce2#)+y!s3fzgk)Wn<85qVLxiLKQw{^ zah4$j-C3Zx76ylocGsuEZZ`btnJbyMNKc_cSf13PY$q*xiXlA@q?i`f3agjEGa3q9 zt~$slXHxTTk#+%>a01D9 z66S^6$It}*NQdY(k*MEaMh2@IQ24w;Xj~JjdzPLMM?I6zZ2f5xO=hCkmCW| zF?GhV5=L)r>QiWc`-Nn)M}*C&Q0p(Vmp9XjV0_31xRE>5l6qLPjyMf=O6Xa>pm?WI z!h)B=x>peNsDSL{D6q3YlYq(|cGU|JNk^LQ_~kM#&y~vy7H%w2HaUSud9oc*4JF9C z0Xp!oJp{;|!xn=65XN)ZxtNH@)?;@LJ561f$!`1UFif~`W{~ao|AIQ2tvTVEjJ>t7 zJIWB#`OV#c)HAp(h*Ku&+{knbkPedtj5=&-#I*T{7BuaFQUbRA)RX)MiV1w6P?zoQ zpoc=q*trzg%3t3-g;5MHg?os{r;@RgF)0U4kl`M5@NIPfO5uL7S0rhMx!4)^T20mj=EJs!s!^77>w*ZHL*<|Hg*6ay+*7M-&8?N6*C#kW{ziIoMt0Qr+c6 zJi`DqDqvMh_lmx}Hugctz+ce!2R&3kc20d0)U8EpQt#0j$~Q?pYlJyC8s|~tiBt>~ znJ};B3(YiJ+x}n7{e&08-ZHpMy6tO_|46lXnWP75QrB%4XfB}aw(B0yBvwP2LB9!= zKe20s%VKg-3m~v<<-$S_&Npt z-3dgsU`HMuoWC@8PaBmE6Sd$iO_(SYivrJko2iE|HC6~wCwUo-^UHq|yF0Pkb1_m@ znf<{kNdGP=et$u-o0Wr5A@>}$!LKFWaaht%IJ6hnNM=tMX1SJ`nyu+giLN5i4N;DF z;A$}!P=w;Ipg=(3RYs;M(hl(+lNU32aQBqyPKTFg>E}Oa-&G^~(sn`PSf&>ZOVSQN zFh4?V-nx~S{-XbbNyz`h=5O^*7U-qoe?eL5c{>SN)C{}GUht**9#WNrTN&2b(BCYj zH8a`6NJjl(aukWaJ!;hEtu%d(BmI%2R~u67Mh{5$)TAZ`{6w--KnAB|DZx2*!3!$G z$Ho(#)y7T2HKf2slJ_T9y})E!1DRKHOq80H$wUgN#B1?OGkOQ z`4hwIR}wt03D^R(BlwL3w`c-=E|+n`q;4Vd3XSCSnVteQ$W25}&`92p0W~*oK?Iq} z_R!F5Ce08{Ggs4`&|+!mrKViAkZwEBp~%N^Uir!R|GMcd&$0g;Z?rQ2 zNC&ZY9OkKP2NCNg4cSw82mn=ta`e;!LHQP>x0}K}wI+H8Rvw0ed2-dImRe}3v2;&G z+MtUaIuG{+c0+#h&RC)^0Hk)z0tQvMKd^xsK8+?0HC9#rjv6?#5kaF=Hk7-ZBE=a< z@exuiW{PWdis7fIF*?ogiK7NC89j4cc1p5uuYlqP6SS}`NE0&4yJRsGENFCus}m40 z)Sl?f>2M`z#9FgvV!~BqDuXjr&6>KA%zXHt>F9(eJPOfVbD7>yt|H|kQijAn+R2I) zG%u;rOEpE!sT+`XTjQ-{tenndO1xbbzoM*Dz|3av=s=F3jt$8%8kUwgRli~Kov5nm zz4bsX=uUyHX{pR;w&b!Ug>IL zD813rtL9xDPUWA-;vA}>RrYG`(;~Q6r&$l-VR`H&x7Z>9SdBOQ%^1% zx)({Edfaqil$TqFrfaO!)>eo`f6$4RJA=-o=#YbrOt&Q==o5gpCE-8AI*^PV?4w|7 zQML`JtUEy>FH7wW;F#Lo$E2?twekym_cGt!)2lg09qL3aUyOAeJD|&f`Ew9qKUFfT zG^%yUmQr9n)ywfb zy_p2b#%AeA-iSYOmv%R%y$xwYn)q1&f=jwrN5AyyzsJ8ABe0R%xE~rhqldH%ZTR&j zzaqzP4szx%M0)Uxd36urSH+YsFuTD(CDg zMq2@HD|8X{XR;MY21De-Gv5A2dxoB|Z0S&xq`B3J+RzW8x|N7cZx&Wkf+#dD`S}Tg zw9kuwjQs-*iMWoSPY2rihu_LtNbfZ_0eUYM<#6_1b^C|AlT_Lb^e{0(M#q!gNmaFx zjT3wr2QLAl-!#KqE#|ENK10P0X)`9{vo7maaya$+;y08FDhr(vcW47-F&_gXQXjkx zuH1@X|1=o1z)7>Tld?uI*i6H8AGNzi=*Bdsz6~kgftnxx^gpS264gAsBQ*sx#HzXF z*8fh;_k>Q=ggtN}EOq}ob(haCB!OQ2+j<#>M4-Xfo>u_H{c+K+adTA z!({}Y`4qR2GscpU0)BoKe2R_U4?c^DU4~DqGdfUVi>;6rmKIx3s4ez6&%_DIg2GOs z=eq`CYX z*|Rtkry;WpWNrYt!$58dAaf0*9FSCTl+*nImE}|)KrE+g1Bm5xVE~zDcuxo*^9|%U zLR^;?QL)9VIA6-8vVqN(#NDb**@&icdCAp3q0hAVi%i5?Uc!!ha12k35ZlnpWhKXl z=yiyCZx%%Ig_`4W{kR-xCAXzBCSnY=NO7hDEdxwYcA zX7&TJ)X_j=zJCQ2v}+x@<^7F3R)R`*2!+Bde;6rpU&Yg!BG>S+Tgmdlq?A`vG$5PV zaxxsh3ON|R=i}~}+u**=+4v=oUlie^h97t}h|?Z;UqgT484Ow5C?LC@fS;w|SupN- z*W=N;WNeIsj82EiiYVIl8><>J&EpqvweA_nQ6K0F8}5QslI5x;8B>O1Vqt4%F=gvV z0bI<1sdqr=HTW;v4%hI$f`bO9%~_Bk*^8SXyP*mBcPeC4g?q4N94g%EMCDQi>K;yi zK|?Nz2rSsw9_=j{myZrC=8E-t@!~JGW6wmt?19YfK+YpH=ffQ5z8!I1+>`~j-NDwS z-;wDvbox!}#0dG4HW^Fd6S>dVrGwqtv9%6@66#%&hQ#t@xK96)NpF2B8Jp)4gp4@b zK?5UVTY!5z%@ixx@9 zift6gW^auWWvb*g5L5oKPEG(lp^K*f?gKG`p*PO320&|5?Gwv18Fg^3@k}JG7!dsc zrq$&*^F8oJI7W&BwrVqr=E8fgA%QFG^P)uPaLhIC4%(AQYYJEM9MU1V@r7JX&deAU zI(JB}vspA(dWi3$bb}5?HOJS*!Aac_;DpcsO}muQA{jGAKR!TE3+-R~(2T9K`hDyx=kGE)SO|>vgHINp0ipZdXa)$ZVD2%FPf%HntV+_j zA*;IbIu7~dkdY_@J)RDz^^tY8Mx>J1L%Ix_6~e~URHhQ%TJ*g6`yW38(igJEpdB9sBQS=R;cmd zh`JO<#~hR70xF^qv)DQ4TRTB6sG&gV33566h2WXTEOCkCWj0g6H+acCQolC|dv5IV zYEEfOau@UTfhNgA#af5*#}bL`QBL;yirx@3AbP1mGR*a5v{w2=q{;3e6bEM@bu@2n zfJ2BGc8$R0v0#lz10tgD94a$PD}%6M%0%8=oY+niD;}*NrZP3hr><|qQSQ3>?K81J zKC-v@opAPI?U8k_6T757JnkLhpmoXc4>YUWrmjaF8tb-qM)Y& z9V$hC2x)={ z!DE$S(@XL!og8yt~QB%ep66r+P=wvqR|pLy~WGP9~Rgo%b;WPc1My z-hjXzj{Fmt(saeV>Ss|%Xo1GRDZL8zKy`QQwm5iTSWv)bI~gn37QRs9bGC&q7Q9?Y zXLGh0eFLZQoAi=rKN2q)ucNep?gI$b;)!hZ0ctT-~AeK)=JA*Fr4R%(OPn_9NY zdT5Y((fILXi+bcd1fJ=Q)LV(}spZ^&NkzEE zz#UnciN2}joTK_>HHu2_#p3xfA)vXjUES`*%1rc2-L1PV%QZDRE8EWad! zQwf#YQVjKdhP+UOJRo2{)W^BdfPLydNnV>)EJvg=kY%%9PG(lRBo6cM1v%$y?mbg) zspI|+_SWYc3atRTp+QxgFrW&^`kr zcZ5HHSunl2E{PHT&iJ<0I`b22tr32=PE^%{0ub_8Sh|F%RNWjx#A!=ee|F z{1Mws3#zDwJ6R1;R$SUL+ef=3PV~26H4b51j34B|=r`8?l#AFQSLlmgw|1nl{=b2< zp5`xtAv-Y5-R0~=h4V5~AkeUxeJcFbHoOdAQCnisjT|vS>cWuSE;_54x0PD>!wP4&5Zx z3Z$ARsggR?+~Q=-cqoA2efza~vvgN=`8y~C4QJUPSioWFdTT}}ZzDCzQ^xMtS!5XE zPYbtT1$dS>L>exfQ4EgP)Pb4L=j>!mrX!i&(IuF-G=@%!X$D!o(SPD<4Ny*mi3KeN z!UjOnD5h~_oUC(tV3=UDz}Vmr1r(MQPFP61DaCFjJT~ti1O?za=wY#U;*hh6>?ugQ zRZc*ynA}HLkgZV1p_*Q^@z$0tYoBzW9+sGlLWkG-hU1WxZmpqidO5k z(#>>#FGvdBx07@RND-ZK%}%?~wd2;vt~h;LNtpZ&l26d&IX-tOW1_AzU#~qBO=0T` zg^)!L+9{L1XRdEyso%!IpDwj~$fFl{nDRuW(^(ST1^ZhIr~}>SL3bZB>6C@b_ZyMk zt1pwFC>esjbLpfJKHNjt#^dmzqf$fi_8f&8G3cR7{#mS>qb$nV7>zC*p?$# zwEVZQis1AsC&#~Pj@WQ`vT)@4WKO|~PJx2kV*EH6Ulw89kBrUJ2-tbp0t&C5TX&tR zEQD=we2N_9HPWD1S8fK!m&ie$FL(sMD$aLmu1w#y3q4D2t9}h!Xj@W+?lI6g15JX| z)Nv4*Reop%54O`eJGAZ#6e6#X1}g8##NA4y7Mu^Z5s&*9>5n8-H&9ZGE8n-ZSkU_d z9je9t5JXz&z-Y%kC+fvZq?+bIWAt3vi3U@em_KQ!iZR6|0_%hBmU@(FpTb1IQ^R2=#^@w4{B@2zM!BgP@FvkF=hJlDE!e>$#m}h_^ z!@zt4925p(lqbpe2m=cZunT}XU>U$Qm!rM5y2Y6!2(a%k%m4lvS>hC+@EjAS?n~-+ zHiV%Unr?r;))#11yb7%RG8xATld6z?-gM&Lqqws~oXx_gmx-;IDz5rb99#dKG=B=V zI-_HMEne=4t2As;|6e=y<`Jou3t^73Tn5zdGs2F#4 zmW_fmFNbOLwNO#B=dU+amG>xl6aKDtonrL02n5<27zR#;YK+*NZsK+qd+-wXU={*z z@4-YTdBCN*lboeaT!O6OkR=v-(QB05B_N_+TR*exL!&z(*`i&HW6kBFS+xU@5(;PLSM! z(HUF}ZLZnoB)Go#s0J6^D@*n|+E}o&>Vaxt;1Ccj*lJ2M@BmXrvxTGe^@w)hL7lKw zI0L6-ctmd}hn8_>z`{;+&}p_Hhp@ls5n7>_14lsuv)42DE=109)8d6l*8-P?2b}mf zdrWn7gXm9qRDT1J%|lxM1}I2qpucFrF1pbiU1zKYu0Gw^7JNC`+NLo&sJSsA;P6{jzj zFE#Z5i)T$JTG`ToQ%A+MMe})>OA7>>94%hd(iY%PX8}rsp^OEL>>$6jI8`r#S(ZZT zwsU2&_Z7$q3}9HaGeC(pzzr8$16=*87=ZAo0SqK$01kx-btNiNbbk2L<;Rej{1{d? zKe)^QK}~JO*pV3$T9=_i;Ijq_g@Ozj9_=!et26Y>MLI(<_0Lx%Lxe{&WFVmonLxwA zn7VhWB?QV|j!Mt zBVBe3T153n+S2?$nsdlr586cCx0hRW1$|;vU4Jx;0Ru&2n$_Z1NN6p?cu3?8#TRz~ z$j3km=RFJNdo(W>4GMxIYX8HHG&F`olHgi&Krn>K0!JWe7ycZLnLIayA%qcOzy&gd zk#r4bAziBwr$R#*IYwG05-@}j%H1JB|74T*7;uo67Ra;RiB9O0`iB!6l(B&F0J3HL zk7d?qg4z|R4$HW-0zLRntuIiD(V{CkSBczAcJCv|4LI^)k&)u%Hg^9J!OCH9DY_j3 zEd+fF&><~kTUR^rH=7AhE z8_#z%?~8XPz=1$DNjsSDBEplO_}BQ(u9A)3Evn#_Ptj;1LH z(HyO5Vgb$1=QVDXW)Z9_guUrF@W93*gnjex(z+7|8=O%3WyqI z*3hQtHMD0I!k7Qk8ru1G4XsL3Z(|J&9Zz#k^;~2kbkHb=iwdlEJ1}!ts9}V~XGZXu z&CiXKELKk4eHDDlyukaxr_2p33qJFi_Ql{+4%N-WXGaRm3dkf?W$-Eb3=2L*pM8T* z(P#JIQ}pQ(e2P9>aeuMSnkeu+J_7|pW9uLY%E07EL1IX7Br!>+$KBXE#dwM{wZYK)SB@W~5fT)(Sp?%tFw&#%5{|yj=(StP-DL5!9l*Az z+rFXW={o}$g+ue%GeLz8M=lpN;7u}pu5S>~BJU-u^FYLA3^kXB$_py4gsdje=gQ0} zX5D3mR}Y@MmE6ZP!BD$J&4qZM15l(+FaLW*nHlOo^_{F&%7B1V_Yo#@$s~o2u1piO zs7YXwDguXC`H+f3jC?MHK#ev@?`P8aE@>{4b}NyrJjt$eU?{fQ{`CZfrarIdct`9l z=*xlDp}0u-wJa)D;k-0`laREFiNZv&y6^=g)0MJC8~AB*&qH$CvDAy220NeFZW_xz zGj5AQKqz>!I|>pp;f%vrW{{*$jbp-$EwJp4OpH>0;QpDYu$Rg1W%Q#v6!w3_&e2%u zpzGe8QRNk4D>PO*n>=9yyBhSXM4zqE`NL<(xvzYOmYLe&8a+tRFJetGNZr8HeKq=E z&N}Ffp8kZ%Xz4JMQGJCDr$;zDIHsi-XWK`!s0O`JJZKei%hg?UMOTj*wi+`U|0dsc zTq#RmBU8s{cFrrFxdIJcCI~@%Ms^&*aP+V>pnjLsPk|uX`1~++;ovT`SVVVX!r`3Do{(tT1s({p)8@#E9isV>Q!3o7p`= zE=Rx?m;x$NGN{T?UmExh=6f~2flhs95-tHCZjdKK2|l_Cjlefs4aYa9m;B+9H8@=G zeC_=RDx4F-xy?aGL(gQdyB@>F7dgn8s{uD_fI1aT8}PIBC!=2hHSMDh)fUouxpC%* zv-OB=5A_?uQ>wS1r)Opv^e}_oQLO>m#!xwx$zCS6SAY*DHS+L58=XxXVQd~bEqVz1 zSI=<0Dqr=)NCopa^H3>d9w!LA+?(Ln$)Z-4+Hg)lWrjK?JP#q&6j13-yzt3!%c;xK zDvHg@Z)?M{G#m<*MP>vO910!nzHsDlWMC6cNsOnhu_JR?T1IO7$Tw$@3^s;a)7@9+ z$XAzTX`RsZ;}R)nBZ_PFLM@LiA7Ij8d5CCp;^0{35`-<${o!w@7i3^wW)xWTi56r1@n%jNhs-^b#+vpYSD(+if8cT*h| zlEz_pVMKl*DClN3#Rz;CguX`#K85oxmV!KSpAdFBP*n5Qco ztry)nG#@cKIfwbi?@7mwv3J-M&10z{7-H$04fZ^w;HUFXF7p$DMmdYETYwkO#PJ>A z;EmZ1Ar8s)z<|_5_z=WQAxL69sfOc~RNX*WSf)S?gfoIzE)HmFdBd#LOxpcGTw#0d z0V!;k1JZ?afhX{yIUxaaqn_8{my@V0dc4;z08_o zaRvQ{a}e?@8s7H-fw>J5AE2=#-6vl}w3Lp`H1fU+bkebLplblaLpDwcA^fXA3)TJ5 zIh6i*fZ;(-oH_#8Vd+#oWNi8v`pwp+Bn>H(8z?iK%4`==MnK0XqjJr zDoyyAS{BqNn%_bkV+s3pbN+YXHXKKpH9U5f)dSCRfYk(J*DdXYf0)I3Pi%!Qc4 zXEsH#TOKs|?1DRCAgU0VP%X$an!0-6=*qtSoS{EW%!Wvmw1i-UX(q#Pz2X3N@?xi1 zrWa43@cX;h|KfFHI7;8E5{5hY_ItWr0OrBd6g z8+5uJYMTDBohri*+z*TYs|0x^W53*QvU=$dlmxCJC_wKjbPYi#30Jrbsu)w4G-0j$ zu?68RI0FejLV~5Es=iFeDHe;F(;C@~?>D#x&s5uOZ{T6CKtH4*23 z#+DTCjupdOp0knRdDe#MxQ@U@1_7M|5PB@R@*W(XQAx&bnrqB_O-Qmar8d%klG;0v z`U0hPi%1nv>ie+N7^LP{sj-mMAir#)Xrcck`9by@C0Z>r~I8Gk_GhJccDBx2g_k#J=p4S*y(2fCSA-{PIDmwF8kvu zRNy!$HN6rQK=fJzKare`ZnS$)h=OK+F4{#PH0UNQugQj)5ycRnw4}<0>HM;LCY=TzW-O zZ9|3#$ilWTnbPLaE5DK4YKzF;O-$g!BGHT)O^Rm@Hjq)9FokiE7=H#fH3;eXXSYM>PV0CXlbC(d zZEVK$|H)>#;A?D#iD;Uxs>#C!&}`mf$DcE6(jo?Bzjj-0N!+#!YH%GI)Zjt}WhkfI zkSkU$F=Qdr{ux=+$V_XD9CbW{2#nm;@reIVM$C6c3<|ICPwYh8w(MkZ9oos@!cAFa zg9y^k3!=Q?KH_w|fhri(R4y?oqc$-q8JnUuF^Iq>3>b0QmMt+)%fx0uwM0n|)mGv( z=9zvO6dt0i3=n13F`2Qlb{Eo}HALjP$E-EBQsnY)!qyPbJb;Wf z@Q^LXSHY&$jAJEVEgUQ8xfJoo&|C`6jEgtGKSFaUoiHx;&jw#qcG!)}SLC5ajQ~G0 zvGOllh?o}0wgeAT7c=1icuxyYIyj#Z)!d#VH{0zVZj#Y0HF^@!)>pA?D;kUp1M>}V z5P+$p16s@AlrXJja8wv*84L^qu>vcic5*;&Q7W`~SSTCnz8f<-!^1O&`HSn#|MSU2|;b5jJ<0FD+@8o@A# zSj@x-hGEHK3W4!ww^!@Yuf$$$)tVIoN7cF_f(ffNIf4nRH6nrutCdGgJLeybPL)}z zKOXV9(fNNK=F$%k|Nk=Zf46B{FcX2XxgLsXVp}C149f{h>R$9R5eEuy4Mo_4Dc}d( zlF)I4eL`E&L|BOfs~)j&U@+4zLRuFU1vFPKU9gp_H}wjFw6LfTSPUVH@(2q7$vqE2 z1zdL&ScGHiP$nBDTDysdV;L=zu?ubqWp5Y>vxSg-8HvsTBd_{fc#YFdg8s&bZT1dl z+9sUpblDToVt`!i_&aqAvL`I&2P}>ti#ZV%0-6R8YEWUmD^G#n2)HfJDOlrd!}#=o z@sVVFY=p6Z_BMF4M()`jNwey2Q=YUx2v9#vK8MnsqM#* z?AzM>O#x?aGm!{9JN!|@4{Uc3%+XZ9bnNsbD?1V$vc}z_I!*U5w?p}nVKDoKS$}mn z)RvhigY5xq1h5$t;hG+q<}yKLKYdsN6{BR9>16C#gc%;gb0JxnhIG+?&#S-XwF(Wp z<#kbnS2FfPy%uOhtr{M(TNlsS_F`D<1(@cf(ka3ox@~z zgC^{QCOW-!Qz$x}N5ad5u%qmC5S_*ax?x`o?(~f4CZK+zn+?8ex#Am*PCWw_=aWV2 z$KmV=s0kpKz1!Qfcz3R~5Ox%$`TrMTA)qP2^ zd)fkODW!uRj7+Pyi#IK`Cf+<%=wd`MS^V$u=6TEO+z_uVL&Ln1u?j-!zDb$KhN)IhZs3-Fxu8i*whGhS#jQ!sKBPW%9Bw3s$H;*j zV1@E)#A-MYf5+9n%ry5g;6{f*7fYD?3XK_V1i0&e-;Kukcf`rZZVUoRW@1X}6%4$x zu=@1&9vB24G)KEC5%VSdnWw$tB?t5d{-%2bUwU}4e$q>Tn=}w7a!ULwkrf*@`8^rm za9JFTXvs1!#v(v_)k*0d%Clg?V?n^<0)MdO!ISIggJR^bUpwiNNXU&2nB~Cu@C>|w z@)3k4{NLbycrPw*RMqCJ%Lw?Dfb?~?D`RQ6??u0#fMgf?4WL5id6hw`1R26%n8L&u zb==L!V^r)V{;i;;SjX}bIS3YE`8OZu^fXI7#ft44F!->U#+?t`*_5VvD3y*>*~A%I z$M#Bp40y!V3HVn(qc{Jlt@uW($JQQ0?z!^4AHO^CdzO6fj&FN zY;JEH^M*I`05VvdqmiGvarK@Mn%yPZ(Y-kheCU_69zDf#E3txzb9?t%FdD8|$b)|o z*)YxGmMohgb5@;)!{Rz|B)H4>TtauWEIrGK4B z;Oj)GaX@kVTlt8J!W6RG!XwMvB`Bug_O9~v6(1Q^%#368Jih!xh1C$U>Q*wJkY4z0 zciu_5#Z8@H#s=UJFtR!C6C6~gWdCQLYboL5z3Ky))TTvHL}}wJZIYMl>7&v=*U6co zu6#VK1!!D@(bB1`hg`g%=7Udakb%Yk<&1&4i_qN-v~$@GB`X1yBYmob-hzHwuu+f# z5qZWt1xf6mLIu^y_}4n6A&fi14@tPM5azWd)VG*A+D}OP2X{WGE%=w)+p0rGW3_n& zszH+ym*^`ddP5Q|mqgj>6R}n(XkFOQ)mYl4lXDq2GhImySg6ZIQYewWqSz()k%G>a z1ivxCi1rB@0e1;V<~?mgH46obbzf)yAgql%j&$k!_E1=Shgu7YsXede#U--xcW#6HAiK&XB(|{Ib_?wG|b$s9kCUXIl{Kuuzdz} zA>00Gq4c4IGnqUwOdSITk%XKJr;A>X#vyf*DW_TB^P7K;Taip70bmFGlqJ6Ym>JhGmj)keV1uSh5r)sm=oC z40-hwy@eesu_tBuk^_O@?#Zz@svh8en;ya4wcO$u!(=lq8qLPkU_`6D@`)9DVtZg! zOJA?fMRc4Zt_NqId*Oi_=+#x?S4D-KzwcL`U(pp5?3|^p0D1rb&j~8Gd~(G^pm-}z zY7$WUl%G&BN>F=&=nkN6BB~Im{s8PKs6ERERP+a`ny9^j+Pl1$LG>yBtm09i7%LFb z>C=(RV%&G_s$B_Kf9@i>7RA5o%>{UkQNqVS4wtQM}&n`DI<2W#uk`0bv-$8 z1u-LlLFCO}hGCTKD(`94=<+9O#MM01hiINpB-!2Ak)WH1nHmVf^UvHTUuXpli3%!Vpiviq92 zHXv{_pg)HrwG#H?RR!{*2D7!_InhglE|ToE;3eUs8OP9PY*F>>n7iJ9^XL=Ro7HVg z_x~uP7i5^y)u#Qr+?3%uOacfmQ(-~}Urgy0IETU&0Ai6rlaaP9VL^Mk$ScIPjgg*)YxRUvpxw%&FIOB7oEz}^l43rw+qm>0t0t|%S41rUN;}wJZM|Bs5DVLZmkSklpka|aM<2s#(&vW+ za|JMPB-sdoLsy#f*W^4I80(K-F#Ig#I3Y|nL=?zV>8uR!+d8DhUm^GH3c36+%EJZBll?^i>rN}L3G4xxT#zH?Vy^U712-j9=xRA-_Q|b zf*daghchgPuW=^aDbY$LW-tXKR&?&BTZv$A0+!nVceflK1c%h&B|Pg6aHa*oaMTc>xovWKp_G1eH|*K zwExA`)JW1EOu8dzv~8AHs>?v-4@HSce*)>}SxkN;{SHjO8k>Z4`s*y!!A$>a#B@86 zbe@p1xjEgEp7KOEFTF^0UBGaVrTY9SFqBX(o?i+I7s?+%_tAv%d>elyl+SdC$q12> zLPGgehju`fP~-5VU>KG<&7 zD~%ZQa??Ouh-A7t$=Himm}+w1bAPm|6ORcEhmx^3FOO(c{xbMU_eR#@7hyA()?d8| zi%9h>;kGLE5{gYu`IUTzPdTTnUL%YXVd^=gla1`xBP44E=)WP7<}s3**~iL;1$3*x z%TJ_%ak+{N94CSoGRAFWp%%dd2;1xM@Ur27R-mhn^=YXA=$KInA}FXL(a@RZBL~Oi|D4G%|mM8T~m8W@@;MEf)0;!iuKDf^ZV??n0kL5E#%cT)@`4j`twtU7yh$){u zT|ViFTwTFfe8;2KhXzEz7^Gs%2{7pij6+x{nFfmzVGLjvvjxE=NW<2e(+OGST@%CA z6WA%0O4CD}x!h01(r@R`r0>9?^Xbqz>P&boykKh7q5nyPaidsUgNYLl*0RW08>yct zqPsFxE&24~9JN0<8!MUVxaEttgG1=c(_(46V~mKS@=zGPlqD4SJhoUN@?F&xReay; zY~&Nv!$6tH*Me+HkEwe8Na?=t11y%2#igJF*IbSp4INO+i8@WA@_^!4%A|UOsKYfX z2dE~Xn*8Tt;0#OFWkQ5k|3{IGh}2K$3HzJz0iWe0j8}JLKjLpgkA?%(!!d5~Khk(k zn|gKE?LvGk3rXC-_BnQ-aC0A$aA3PenVa9%F!a0XAa~Ti#yw)Xh#!HK)g+{K1KV2w zBA3o;3L>F@wieAvAg``VPZ2!`qIu<Av&eoL=#MQa*m>$jqKYbW8E(4 zj#8RF0~}G>t+>eU3sQFmwg1zx0zAvBI|ljl>erKqgGO9Qjlaz_po^p11JoD=b;k*( zOqGU^3O~`C z-^J7xrhcg@&6^#B#cm}(Qt6Yikt~5LO4Lb+Scztcp3Z1NjjJ$eU8Op4XFP6yF&Ut? z(|WX)HG*=Igk+>mA+6tXjO6@mukI`S^6Ee3cQW?LMQx3>nR3@+ua#P_XI89ngm-Ub zF;izz!Jv}!yQz}o)t{}Uoa5E)h8p43uS9{0w%WeJVq~JfSPt`^aW$KEs%n_*T&PPY z$gkw?F)gMNVjTUAV%MU^u=N9tPO}W#lQR!R7!@=$=DYcw$1vE6#Xf; zd!b_71@BD6)KdtiD1n%I2QC)L3L?q0zBF~ZdX_|K>NET)*#b!=U(g5siNZ_mEV`pq zwgbVdAP`Hf_e-D(^txH}+KhgYSD$_;rZmxWZeb_Dt2-o{%KnwJLR_C?!{pWNBRSZM ziBahdgEDl2SzR8%d@#Uk-~^>Z)qa@Y#s-A4H7Mp^6Olg6T6B9rgfO!ovz+=2rTv1m z5b7!UgCt9lBwCFIk#-SiA)}d&);$q}pD_gDkX}s5{#aL;q_DY2*=QZKWQmwXb3h{s zOJlNHtw3R?VyZtR`zH@a&Z=6@MVP`bum12}3{y%~!}|VUA}d=y6-)FMd^t{a6MvqL zDykD|rr$%;Jt=g*6p~L}j#$k3GHxp=+f|$GZ!$5sMlD4~)KhE%_GkVtaQSa-Kz{(2 zO*BsHR&o-p@UKtlB#r7SB=zS&0@Qj@#9c4q4&K*@i&o82Q#CJuAEeU!^O&%z;^|~pPIe{BX@WDw-;~-4v#9P+ z)z8!1cJt~cbR)M<5iK;gxtg15H_cE(ru&d-RG7d$5r%o+H042JyMMIz8LFA zk@F$Wyl6QE?XkI}4uy)~yJy}GXW<<)n>zbeC~wtX1fyKB7r8I(rAp&K}0 z;fqmI`(+G1Y&`K!=I7US%nzflS_2zthku+oc=!m(!I@s&&G_Zj*YaBeac@k=1rp|A zCf~n`xXPB-#ggX=`DFa7CZRHSkjYY{;b;+gWH$c|e*RF+f<@%j9S>`H_2L^jmW9pf zoP?;6v_7z5)7Y~=*4#$fC_=Oh%@NXh0G1jtr zG{3m^fV$qOi6?t?R|xS`ev4@`(BBNH#0%B@$;4K+tdN{NgMTaX)d)8G`l@INAExvt zaq)-u!)e33z~sGk@;4-TXOWkN_^VpE3qM??onf9r`GweA0yf(+%n};r$2D{UMtB(J z2UtnF!9!5ezxOcFo@L?H-GC3Tz7qc?cpYe7y863nvK_p-rMa-*P>`%Jy@F?iZUsrZ zeTLfiHkw=CA0|rd=+#vr>U#A){!R6OTD{7ZSN{gSM0<3HtIyzvNE``H0GnaRS{mm0 z4*}A%KQaayP-e$Kg1#SUGX`ov$_Cx(SjUuCGbQgG+YeGvhZyR;`Wx^sY-@`5V)&9I z!z!CEo04F+@;(*saEF^EV*Uc6r;r}}CWGi`dWj{f3lq)MM8B2qQL&pQQ71!^dKL|g z<&-)fztGD@H-S?W9Oo3e$grL{`1k{s={o$IDlo*Y0dcV--az7~h4@JlcQ-Qsf`a38 zygwODI3)G->WcBps~^E{SAfkN*WeBq2~fdCr8S(l4noy0lyL%OBnGN{c&qvvW$kBZ z&O3W`-%FeG6Ud~g+{vr^SRfzZUtPK-T1>QyWb+=%&K8PldY^g!6#u4G|Ow~B!SSl zUzbd99s-_W_j~j*>wbdn3$(bO^mPT)i77aSuWH#LG`+-Dou!@OU{aKXWrkp!nj$RA z!My7E^e0zdh3JQYjB`jUI0c1{j#961RUF#}+jMriG8ebJ$IcFum^LWW6|4|k27S|aA95_wTL}pR+ z5TZ*K1EJ_HDGo{6lkP)K-Gp={NjJb?Db2N`U2FT2{G(OiOk+K*-S7e@S@16tuO0v= z61@u||5A)skddxl-5L1h)t}C9=Q=U;Fh#w{rl1v(s(vs!9Lb_VIujDqFX(sq zJvIA6ukM{LWIt?xsqedZbsG*LPhfXJXqkrPSUED zUA?+zBUFjF7I)T4E3 zX%Xs%;KQpwh#+Z%7IO$;yE^---H-r&isntRQCOi?BcKF1>Pf~Q!Tm6#lTx=`yOU_d z-B;3xY`E1{*pn>MR3p`xM~{8|V9CTP$;5VWU+@1B_a4wy7408x0tsM1HYg|-G!!X{ zihg2OKt(}Cqhjy<7z?Px8VndvloO8)#g3m1MG*^jC14?_Xv9M7vClS^fbEDt?(=(R z?^8hie|N3B*3DYkXZFn7=bb)#Cbiclu^9RQIwQsicLNBq7|f5=x&0ACR;_ct`!a^h z#mtWq^E)XwWp>Ac8xM0gNK)=tKFCj;ogK;3#to5zd9oib^y9PWLxui3 z{D;jS>`1TOsSxG$glwpXxf8NZ1em9J$qh4PCAw+|I(xNM*aev1kIF)u;teMOmPogNVw84=K4 zHy30Gv=M>F1YMmzB}g7d@2pB6&^D-_RafRT_pJQxsLCKO!zM|kS#L=t(WJyaOzyco z)lBcsBRtwuJvB(~V=@iR$n>r{_iA!-Cnn=5%8Wxz5rdIpkk8oS2N`1<*$oogH|cnV z;nt?dCPDIjAL2qhtRd^{mo-)4WM`&1S3`!A2l@W%u%r?O{gnh8&F0 zSVC6cQq9#-aBS-8(^^@Yx@B%(rR`1{N5;By)E(5F9hqkBb}2P#5z#sQ%h$@|X3dg^ zk{mT_wO~g5OMP}6ZYWIO&=0QYmrcA&i7VfPt1btc?e--DER{ZH)95VR-GX}`xQNK^ z6)GhWhyN<^nJkgXNMGh!q=R5Ys<*2`Kb1OkC3d!{;pXBU-XWi&u?bIPza}MVzB%N+ zyf7!d8QGv2KQ&oFa@#xmWdFz@xlRuWH%c9|n&RsY z%g&hPx@!elUp&?lhqTLc=a z35Ii22ImJx9ujXc1(c~gFWzi$+$K_O7mv7mknEyb=XtOC(-G1g5t0dasgOeDQX7wS zGB*NlAqjur=@BpU;~c;3gC3j)-nvPP5Urd_y!Bm~?;Lv+UPOjGH7alZIB|PCfBX~K z5zbs_-i88zPRR#7=Z+ZkXMv6f)a{FSO$BaGNqK^#nvk9Y-yk`{1l^NoI9&17=|h6# zlwt<7x;07uVb1FkNx;p0!%`17DoA!96vO>&ws*dHO~{04W(1&jDC-}Dm@nh$X}%o6 z8qHmOk%)TMg|H6asYAOl13j&cMeAWt>(U@O&1h|=xkFXbnF_f`h%bOx=APpjULuSM z=_RJ+uk9qju|!!hzuqDbFiOJ(=S!rbD>~*Sn1_kSux0GFnK_%*WtsMPKO7=6U*Y4e_Wlp?OtG?W)2UQduT0}t z2LtM-(7Hio?opZMI_8&A^fA+E?z&QRtfH)iYy%ZMT~>zKIi_v@n(p5b969ASrSt7$Cnnv8%3=R_ zwWa02nl2x)={&4cziLAIQ4?|so%JB~Do>M2i+QHzAmntFC`fdJ&c%doEXWi3X42Mx z)bi6m(tM&jP{3L%{4zp0CI@9E8|zht440(YPZ^fq99JP_l5#hs4EsyG>h!oExl4PQ z{y%H;ZZh5N`^$dnMk|du9q&VhzZv+^@^o8#r|A-41kK4r2CZwnG6nf?Vf^w+2IKwL zz!;uS^+>_IEg1T#?jHH$>Rqt}6mq61qIGTEHpZ#i84V4mvx%0*GVT$T zt{FVSS2r`c${7CNWAU*?$WNsUPU$z0`mUB3|CZ zoh|Y`MR~BNoT!{0r22cRbWEP7*NPXZYC4A|HQc~Mol*H-kW$N$!}~D)mqlMBg9Q3`w&HWgO))$>-)FpWOEa1YE<-4dhjUxQ8*T;64N{ zywr0$vogtow&xVjPOt0P{i|iF#rYhOC>ykp@VVg;g*sI?*7-|@N!SH(%C`sQ9?oLL7r9uMhD58zZB1l{(`vKt-rCe z9Qlu${3|`~Ih8L3sdE)JsMZG6;0{EnDF0>=43G5CV}j%`LP2V92IC!#B2+{Dp^3x> zS0(VxJ@~nmZ*bpnQB3^)Xh5)xDkf~}K`v%Y*+vxi`-8T+m0JKzxt%K7iLX25zY;0@ zkd8cA-GB*$33` zF81Ib82CxN1gT>bWk&glK5IgI0R(=R!1wjw`qno{PDc<{C&C;6LY0>KT=i=YZ__xG1Z*bqr<`1fi^;&n6 zX0A!|C@<81Jk7gaw8&d6@n?AJd|Bt=eghFylZerqe4r?3^$t!3F>vUcD1Ojo=X14;y)z&+s`3;;vN8) z-dp6U_z(OSiMCBazJes8IGAGY)J+Rd(xiBG`urfd)pGf17XZ91KVsMdS2e?p5Y1*= zi@2R=+*C!t?RdBWO5ZEaT7%h5Fm4x~Xy`@RBO}UAvh3Fz8TX1Hc@aQCY7w0}YW#a) zU0xK`_#dLZYa}Lo%0pjRIl!Oiz`nOjY;5J+w{vqa9uUSXVNCQG7X-;Mgo0GL-mS)8 zp|u$`E}hbYa(g(6YYaVyPv0h5mO>YyCY8|auCMvG@LAR z-38rS(91V86HdTjLGmkJg4Cxx&6mepWX-R#fWkQra)GFsgWQR|xS8&J_a64d=3hT! zHkWq`hr=9Z^5Yf}O*Qa@!t*>x-I@;5hXy&kljJgYJ5RT>Ivj&|ga>;$F9)BgF04SS zswgws0tO4_5;}V(lh<2{*g+zecn&mVI}j1`{lQ?iG=^J<;X>v9w;PyEs*TsL)==!z zI_7nBme;^6uWiNao2PSlef8|>ybNZZVBB1u?pX1ejA(C1jOmD?FE zA}YhVm|= zteK6lo2T2J{ojPx|GhrG(8@JHI0L=5iV_zmxi*IsB}07k|HEEp1EM-flS-!YMA z>dQ9vX5LG3s;X(Jv(D%;Bx>3>%8zjaFu>_Rh`_tB$S}SU-!{gRaZPtUAn|g*FLdN7 z>MHF`FCouCUY@nt|7r5cw_FrDdz~aqdN&Lj3n8 zB20SJs|@uBGMSx_^dHEM5r*g79AwE%oLwMxM|hlP3}>jZ+l6O&Yu6Q=4D7yw9U$21 zbQ?CzFHvb4O_NYw!}Ea zSYP2};j2QJke+QK%`%)B!YOciy?A)qCcEl4RUGI{{qS;Lpi;fYCVPetOvzP>n${T5sWCQAd z2E%+#7}fuRYw2QY4-Aq6I#_5>)c|Cl3m|edvWI?PncGa{J4I+}&D@U~Rln?Uw`ct4 zL%Rg2`v`$wmBrt_%zZ;eK;O%=ycZr(S6{&NNP(-Yk-QccPxp*3YCf&TK4o4aS(24qq&niEfA5*0_fdseMvPQG< z_fh)8$35_S`~=C{^h{0VY0`Tgui&-nlZ-U`xYKf^vBmODk;Zuc-K5q$@gF1p<-52; zVeU#KtPWC&_sit$*?dLNdqmKEBT?J9sS2%-r==^8_Z%-6uE`yxtVA8MAQ=>-;UCg$d7F z$1M9GU_tU|UV_x2in2=OJGv|7D^!aNgHf3qO;HJlcntL}f@FWg=*5$|WF_DT?wEJ| zc{k1Ht}}vrZ_3<}R7K_MM!vWqooUyD(Np+GXJdW85o+WmNZn6!Pnmf#OX&VwLY+it zorusoYI_=h3}<;l4;i7Yaibu0G*1YfnI&{=E};c;NbVXDnk+&o5jxcqy3YvBel?rod#@oN$mF3`k&S!FijvH*uLZ1Sc!*eNf65cO7xA&T>8#h#YYbixKj~?INTD zvPc7gvQM$hCPR3W3qAihlD>^khd*>QNwxez`_BvWpNh&_cN{&Xe8DynkMAGOnB+}N zn)o$i#}|1uggn8z3u#Uk>1GebY*4PXHxX3IpiJO%fpUEi)b)_GyL)LLFlqamv^{v* zr&kyH+>bswI}F4y5O{TZPrmhFO(aPDmRT9OlAch$QvJlaYgWELu%UYxuMZart2(_$ zkZi}exoQ@8(VFN0;k-B#Qe2R;Ea+6QEa*IJI)P!+>7Mdo;7j3s>Q78ae-8a1 zc?~bD0P?i8h`sp!rUAq4<=wvny|6XiV|SVIriU^>qZf13ntc>0gh4Q4aJtYC?Z%-lCfIzmC}OP+}@WEO)d z6ikDM85Sg8F_@PGvoHhmDH$F<>0$P+{Gh5!;?GRlJf%(ZY5N4piG)aBnn}M~=@{o;g`FPB82okU`am2FVxc+Cs*}w5sYTfo$VJZU&@s#~?NEBkXF8=R+)$q8M zS3uUsAE$VITxu1>IlQ?ZXjA6C#ie89odnd15A+8rP(&xSklH<5wU*`n=0UOt)(TR0 zL)GnqxtPzm#1#p)!1r%@p?~*uMx=r zl85JzydZ~Ud5r&uYW|4mp>gC$5ly!_5BP2t%&66a4{IMr+-l{p{}h2UK?I-TJ^%#^MFLljvmSw;~S-^X>aG)!1Vo z<}{7}<#o-v?_nX`nnkMgP^&eKj|gh4L7C?t29#@$R;~??uouY~poK342r*H_fY17Z zYI3%6stY3Zv)e=LOTJlFy*Idem89nZv#lfnjF2=7+se%sn-}QG!zLXh?j7#m5Ic1$v$@Kh3_ zvQXaltx~JgzXi!B7zePj0IiH9`?z_)$avZ$Wgp&MLb=G#_z#pjAKasiUjRe*4EB?v zhx6-B1;1&N@?xKKhb8F)_AzK6plyi>Px3PS9wZMS6r_ghU0)YR9xVSGjgs^=hEYCN60oPdF@E;TU()I}QtybE8lnS@~*GgN9Y*&fQ z()K}Mn~qTELPGg^Hw)=BkZc8hXQi*c(ZoRZ6o}hAqNv=E!4Kp&T&fw~>h!W8`Ke|4 z5}xMHOM_%_q3qPM%Cb3=1(Awg*+y`e{=2fZuw6~rwB(+3w<)_y%BILWsrUl0w*TfI z=xVP@{H1VWO}c-H?qQzpc+uS`3?}Fq3p^&hNLT9u8lc4i~Vc+Rtm6Z1rt8hI6%W+__|* z7~Ba1w}~nZoje4YpZNaY#Oxt4I}!7vuabfkH-dPL;}6cQQ#6(FgD4I7M^V*egzM&r z`s3e=nkjpR@a0{Sb0HQK_1}@#T|g@l-hc-o)en6CZN79dPcvszkbL7G%(+y9Y+Ga5 zna0f>g~(JpGgv1}R4Y%_Q4*H~T>jqNU8KW-5-Bow)0#T??`dX2Fk6in-ul90(PYC& znf_+{8SXYJ19vwP*+>PYz7LW%<&nAj5n70PHlESQAwuEb z93qszg1C`1sJRnK;x(KpWQj=KDpGR6Oa^op?1_SP$MbCJiEKwzu2a>?WIDRCnYqwc zh%ZUJftQ4Rfq_6YcC-NnOdX?x}uk?3*(FTG@}L zwItC;gq{GB#9MsgWF=A;lG<0PQm!eB|O*1ubKCbjv=o@vI~2t^UeC zzQ5l!SHKttoRigP*b1rS4+JEwF4v+ee{@_4e~VUJC0jW#;ju-JrC1!haMbi2IX5!OtTk zu|34+^%R*%r*47FTz(Oonq7&UNR#v%SSf0BZ-Gzd%Ne87uW&@LI^oP5f^wtW_4`{X zQe}zT84S7;c8p7eC4Ed1O+5rCN4_it6Gu?D8Ih=H-6SIS0ZGy7R%SyxtUA)l28Mt6 zcs8nJ%HhodzDU4R#&=VX!{o5ole`=&B}c;!u^g6kNLG$!Xf=ZsOuSsh&cC3_Eh4-r za4loHtrokM*s*k+k?pa*kyG^bvWXrfZWW17ZZTk;>SvN1kdefa7m^%Vq&YknZduiC z7y2DpbTep>LAT_qv*_vYp;e$OYceMhx298KM{aQp9Q%ORqaLFe4mq!wS*51-BZ7P8 zXHQBR%UwC{w7bag)=`bnSLH&Rdg(h*t8CFyG2AVZLu%aB4oI8Ua6OR$C+Xl1rP&B~ zZW&% z!h7r2rPi?(>~VcH+JXz%O9B+N+mT(H=Ra5^?p3-w54JQiTi#~Sit5`LZ9@G6yD)DjusW- zzKdF6L%V(#?_MNrSKVY~eHWFnvD?LE%#wa4$$R!BopU&RivLkbyT&pveuviEqV+fk zR@hcgxP=7DTWO}e4UI*+{a9&`179yfXLxuOITP&T|HOh>@?rUcg(txl?aq2rUe?d` z`O999<`>t2DhX8w83sD=|7*2Nzu5r6fdfuf+O(3ajo~is=mzi zZiMZWVLL|0GpXaju!~OwmPp92r(!uvo|m?B-*VFGqO^flk;Ai|9!Sd=`SISpqFkAG z7^zOdI6PdE61ZYN|!fek?N=im3^sK0vjC?Du<+l&jW3Rq<^ zko8JENKNr6hCAG?eW)%L?)rXDOK|P!#!+q8xmG?<>;6=i!+-8xYK{BabnDs6S6liT z{W>|!Ew9Ul1(*i^_?Ma|2a#iysY~bqn5%w9)grBLjedu!O6T3Gc779^B3$^LB05fgiKCk+Cu zm>7IfMfZHj-DAknhf-CZ6_G90X_NK&kX>TP9Zv*u4@7L05wUfJ|B6W>mBb=pgnSB% z@eQjxOU_rdY+mQjCIwE%!#?Jn2XET?ar36S?&dUViNf*=RksyC{w@`ZduPD^`&-kZ zhT-|^brxpSwE6u3Gl)`Zw=#E!rAB8>`qZnlsZ~)BCm3sh-F%@@$0dJcTU35b(-mdz z0HD;-?Bt%E!OQ_pS79mw(-0@0%FaNVxxBZ_d&=BdaUbw!9*oMbY46 z0-jA2i%xC@p^P~riFL17OI2`JZG5I|XI%!OdaGc3baz~gqT=Z<0U70P?qwBS&dnQF zf)RFu0}Y+-B=A=z+`38RM-R*Zp{DqHy|;LOicD8iJShhHgm%`g;F7fH@)fD&PpuuU z#xOp$HanivN<_F|rPO?tXM8mb%Ho*Ms*)Fp>c+N|e4U$?v)ADcp>kL~O>qrDH;tg3 z!dmJ|=+DGQu=>MX-PxWNg(jkv+0PoE^_vyyK2hFQlp{CZ%|!G5XIHqFy6&DHy{y&g zl}2X=XX!mGdS9-H=yi*!78_MxDE;xViL0c@-jL23qMK~7joW6;$R2LvH6zz@ZP$z} zbj!?hd{Ohf%KN)d*N9BW3EZn|#Btz{63N7GI#J9I>p-;AUu5@d8YA| zPM7VZsewN*DppEU$NQs$AE4zjD-ngq<()gbA%n5-asVP-uOa9THj2{M(;@dq<3pNl0@(Ynkf? zWz}D4_vSRTswqCs$c_`)?8pb1NZOO6oX)|oGHhff@3z2fnh*2jNrH)5k(%Pd{M0U| zzy;r=#rtjpXs>Y~x_T}0rv1rb@0XZ&^>ZIbNzqaiEpwajWE7(MRZg!QYFo8F+999Y zc~><&e^DhfTuC>5Zu(_Po!d*@4`z@!TR_FyRmw7lLZzDqBgB#|om>&w(lpph^^`E; zqUEcstdpKBsjh}uv;uJxK}qpGzp+I;&BP?6bw5HZwkH0tzY0J!s8@G}UNGHyyMSqJ zPf2;!fOD93osgr{51KBtd}plFQt!S;T2nKw9!uS^G7)N`O~0u6y-J!ME1kNzFO{q; z$)2;G)yXbjdP>76Fx@rCvBoUFf!rVvcdujsZl-CR>ED<+nfU7D{zQ5%POK>&sIu(M zo>1Po1Hp`qMEYCUCQh$a`qugBFXyB?r3d-xr{ttJD*fl&`jTm>ob)=Sznz~R>kZY_rB0Z#=xw--1YKRn?%IK%p;PK`n?+(?kLilwv_G%VH^rlbRuT+zz=B-31RV^3iwCB``~H>I$ANEYXa+>`>P z#5lX>rkv&mBAvIy8fWxtax~}M{;@h*()V_>3ZW|pq8?A)m%Z%UVbzdzeQu5AnbYw3 zN%~rh^|uA%7a`su#PY3~v9BW(yKi|xVwrNHnz;W@gi*x5O<+us~-AKlmRtnk*juc1h!r$c)6^%E;{_k1EJ|fM(<}{={%1_A@?s%*1+QuEnmviH+G%{kEI|L$S-6ykUxTK;F2ODsO2c(P>7@&_|Qq z2MXvv0xC=BWHxtxk9eNRl6sRAP3@*3FPDjZ9p~9BilUh;6QS>$CC(5{26UtK%z@lB z3we+rYX#|7os8{@(wMC!KSFZMw&_a4m2*a&nw)7OIvx}@-`lqN>QhDiBrnGh+Jt6? zc#gRoej2&(3R02gX9#eotQdA+X+=g1OYV~uqXEnYv`5u5h1v46S2b+b&VmVPEocVG z;q19!PZcxP;Sz~8A-%xjM>DM!#p?@7@|TlyH!|R^Ji~{4OJ;4R;O8d zz1Pz2RND5$uwUqUi}?=fO}&X>!S+YORj+YAC#&I=KU7_9tBJ*0O|*>@8B<&$Q~df9 zP3IVTHqGu1--XibO?|$r^o*jg-=#vD3lgrPS^1V6KPd$)jr-L5$>vId-UujT@O~o- zTk*-%cUmB+PP0kmV>9aeJUN=tHfb!hn3ol^J2C8Hc-mqfQ_KKjmYE^6NXl~UZI(7w zX<9vJN%u#pG|qtIna%A<5}~uHNSoN~p0oZP>iwIFR|x5oAO9B>uN3HGfM!)JLL^-0 zUNRv_stycNKat^CnWhM595|8L`}{95C51HnpJh^pkvla4>me|GSh%17Ce$6_7IgD-5vG3+hbT6_yudyONj)V8>qq2urr5?tXFZyZMZk`!f_FT+s?OSV1W9HyTdF37`tl69G^4^H3cLiVTX}{RS$*V z=)F447sUe&LnjY})_JZ@Ul1fU%~kbw7*&Wz1j!PEDiTywAs$ZF(ut?;yT#Mu!>wsP zGzk3(h2#C}+I~+7=MwSWbPjB{ue_A!E>+Jooxm@jLRyxjWbCE`h~a}d5e-tBqHfxi zn6^4$M~2`COy-iQ_+GOLu|s8Z)hrhIIS{z=jH=VEwm33KhDa8qhN{Z5#>JBjD)+A1 z%Ru;I^<)YU=Y;ai7T!mc!?huCEYv)?m9=}(af&Q#G*SwO22)!#QP*X09v4m$oT$yT z#;R_ExXrZWi%E{!OuNOw4s^4R-$XOp=?o@rqX8#9SBsxG6MO5hHw4l^zBc-m!%Ko@ zUoAW*2})oQcNF%`aJQttT!wq5YMdxffJ9WYydV+_fK$Cs9bZcq;WBk0qVyM){y>yY z(_L#xEY6rEBA{9UT`r)U-os1XVoO-^=p0$X(NfEwAskH99$f~vKep36PW9oMa2Zxd zY8`poGPWXuqZWKkY&L?9F7))+acr^0(hFvRruZHx<;>5tKZN3E30E77cX`jE*NNzB zT1U*ST1~rW^0LUf%qCNAwjr*%z`27{Bc<(JJ!y#BCJZ;``;IexEr+-*QJ`b2?GD@xEKdiTR6^Q1d%gT$?I?mPTLLcMBkw|!8NqY_9nzhEru;?qv zRsXG@Bx@PyCey{#Vs?0$aw@AGtAVUB#;bulw{4Fr+095L+4X+%q*>(7hMXz%Z^|tg zrilvqdSmpf#zPL;fOzrJxqbHd?@G5p+{UINo_zYuwV>J-+Q@bj9cRgQ&~0i#cO$C5 zZ$l?$T5NbSyA zhEIjmGquR7dPent!eiIPZq)N9t~S(Prm`w%^AM&lZ)7s=DU_b&i1a zSwna$4=4@@l2;J&XF}uxf9>3L-TYh#H9T8ZURCu$F2wW* z!WtrVQ@8ea5oG1QEEj_Pb~5dCUzyVBXhEqpEpGu;IhG%+eAf>S}9{WuzwF5H_v`V@Ge~TcB zs=82#L7=in6+YVNo~NmA+BD)**`W$oZFGlgX0ar3k_0Y7V9B(6JnGgICynq-2#3AA zfWH6Q-g-FuNx;pZrcPUsoVTfDtlN%Am0@}o9S!XL{UxM6hyTI*x0*n%@+w3a%}cVn zU)&2uIqgr!;c@MMj-)#53noByBP9Ef4ptReQ@pHDD$h9}M`i0e#ws5ft6WDX!Bm#y zvC5j&MdkBFyfefTs?Yp_Qh#2df4$LvO!Qd?<%K)m%aqXqugtYo_ zLGsuAWP+b~nq5RSNPcdSA1YFIp@X={Vixd(ct7LRG%`mM;Z??(91&}>3fDGGtp6Wn z-mOxvBypKE*#~))c~#$-3U3$4L_a||JWZ^$(;-<&H!n!-wvl(eDP(gvLW%Lg5sTYP zgR^L{$~(I^AQW!ylRqK_VhsO0u+9; zuO)It;rVSv;Xx895RFm2uRdPR=(!_Fb@@^Lio$*9v*6x7^|DRvqoMz(AESMy)VZZU zpn1#4H2-x?Dsky3zwVTMg3sk}&aOEcC4nZS_5D$h>}^I_A3Eg6w3ZS$SPPwhcj13U zlV-Ks#$rPa~Gt{761c+tQIV!c5 zDd9)Mjr|Eh@-;$1s#fpx|5nNDxn=BS33D{UxFvqJKK2%qX470gonk(1vV6`H-T02g zqm5N}D8lL~Hh<=`dP}UDKk?pt!8l~~O#xN>VkLb@61D$8+_jb@bu@x&G~g>QcCBT3 z-KE%p;%AAz^QQhdnQT4NS{mzkAo2`-i@Iokqc(Kvy_Wp=ho0#Mehbhu)=Sb@0Zuzn zq&RM)ruYS%1N3L2F6rlzbvI4aZPQO+<95IV67J;>}n` zsgdoPWmKV?Q%^y%E{}VPei0EZL?BmMKQcuj0aTuih15@-5&cfL-|As?>Zw1|Nr_(n zI(nJyG}D@@^N|?D{C2E%ug<_aZL8?m&A=8=-}dHzcGtT zViqu{9sW+*Y*#((nRa0>EW|$cV)wN#p~db;6|3AL65~N=I50Tj$Ikzy#&4jE;Qa{&aH*(U9Z{{66YQ}eF`af>Qk6B)l+l=os zByPrgNyyZPl;!KO2hI2t`yn^_gOXnu`wRADU?bL=Z>wOeGBRzoOkAaJEwEiZm{a}a zFYdeo_qU5Xw}|ac(t(g_G-sZdZihBe2XhCJ=mCkcOnUwfw338@tZD!xF&{acPWoyp zb|WhgkA13t=IQ&{-n6yL_cV+93AM{NXCjK7s_Omxgv#LTn2%Gjr#1ZD@W@8FvFigE zogz0AMcgSUp%(TnIY^<~nY8d0&){*y;rn@Bf>b3>wu;kR&yd+0%rbW+ei0^w!1ZB4 z@>JGzt2XiC91krGLf|EKqi7t$-903?xNS}-h8!eF_L)bJn+vjwhvbSg-9;OumhS-% zQ?sqnjbH}@tEJoe#ND#qhblYv`n+CW=QVs?m=n^kn>rh9AY#90vCxP;hZY&eeZ=@S z5B`RMPvj*?b#Dc&!&F6c^pg4|r}^+S3^EPHTeLA_nv^_4B}z9wnKMvjDDrJ=8}8-F z`elwSjci|@)?;Ih;}lo~sr9yi(T`LWF{70}ye6XpF;exUvSUR3x0D%2i+Jl^-mq?{ ztJhPqHjHa9KuE=3?(?7AfMc%06z`b)bh>q+&jRe)urr>j8al#3sVdPVLrdS25}ahMGYx6mruLFTk&v|5eoSrCex!RSQJkYTihG84{&0LpTA=pD9rwmp`1RS`jVfe*-yl}k^fXdaVk zu5Bc`dHQQmbbY`H%SAR`g<0BOqL$)jF*4GsrxGKX;lKIYfESFg_6N2Bm zLvbF}`G(4*lO2JUagpLVOf#ji!k=B9((jyQ?(1=G=t?)ZL- zN{8$Ho++x2UF)^GGynU=N5!HwETWC50YPD{2Ugf+cgrj;AHJ9NFG%gWBJx7Fh@2_2 z`;x++cQez^FxMI1U#4HIsBHb??lNfIs};^uQgxckZ#SfC#0QUmA)VENPfB{tFUPwE z&s~fIdODfL>?MgiiUid$fNHy2+|XItj!H|Y6uXlMx^}P*_xB>|v+yAKZEx{?xCe3= z-(6L-PIIk+&SSsqorwKvY!*m_cSwvjuIXY3uWW9sTPLWQg0i<U<*{D%st^)1CMM zVn(;pc8hPN-F%%`#%XAwI=@yz()sD<_6LEyrWjD4O>>8%1ix0++(K$Q7XZMeWU40I zmgYjM+v`1v*iJI|5B<9k6q7?FP(9ugcG=Z3i!~vg%~my>qstCK62_o9THI}>L2vUe z2E$5I%UUw*_(EFgLbpXE@p4Kh@TUp>H@dW8t%qkx>0v^gWTtn^h$o~{P4P<3dC8e2 z*?AYLain?-Lek}89Mf%!bWrUis&|QMxu<#&w{jTO+sR&}xDNn|nFHKiD7ZZYHz7U2 zJYfq1eU7lrH;uQ*%GPN52@=^!Lv&Sk6OAEaeY8BKh?8W$f7@h{;TL19j4Lvbpp;Ep zV-NKovb63Yku#{VH2#?iA)XY_IAlWYOvK1KwV|FYR5rm}%dgvB2G~Z$vtnn1yxinI zj+Y>H1W)VXR$F8reL*e8SIE_AE?L{AqY26-YkOi$FD3DJ)W(B1?U-r+cJ(XOV*gnQ zuc&91P|3Q0GHhq4;#;+r)+py%B_BPCG#wbSQ8}!x8a5fyQJd96IkLkdqI24;^H;8j z){iW?H_2mDB%Muxc^z0JPCDq&Arh?)dC&*4VHQYhK=&P4{cb@X%UZ&izB)2mSq^04Y zXF3M}H)g$RYq1&yE9mnK&l5&`onforg|zN+47p{*O?%SKyeH#>nV!geigdVxM}5Q! ziVol4wEbU9`|K2qwsvjci%wU|ntJ!A%HZSmMi_j(tEg>{F$n@h@wf6`y*4`v$^)bd0tIZ>vlyJ5a&XXR8Th*o;&f|34Jf8<5 zoZpRKBwhhHZU?jtFZGDrs`m1)4EA)Z8p53yAHh`xM zeK?K2)M7RigfGoHjo#riIc@AO%5*+3AyIoF{&8{d2$XLw21wsIN=~SX zc0;X6w2tj(Dl8S_eUyQ?Z_ZE@sngtLA{=*be4|hcfxm59&Xc3@az#7Os0&!3B%m{XPMzD*>t?(gcW{{c-pUPx33=!V?f} zPNg>qI%Xu;C?ZfUtF-3C=%xi;qy^&Lyshz`Z>S&g!fj*}aBGC;S>*cGFPgqI&rQA~ z2i%$F2KBBJl-=3noBRsDNSNn#&d7MNNig2cJ6(*YxkldIZmYw8L0c%DrnwOj{B<5) z=KGP1G}rc*Q|iLV$d-#hYhv!8-XDScQbeWReU4ONXQ@}6P6Wx7+eo*y3S+w#p+Qu+ z&JpByqyt$VB-1p#RsDSSc~7@0_-#SW^H67VMn1jUs(!XvadhPm%-AvN^f(WhSq$e= z;naAXb7=ofhV%7q&M`hR;3~i(S>(In(H>(AH|Q9~&?^&F-S)8T#y&Er_S3J(S zLGpMw&{xh3ex9btE1L#M`a1*`@BZ2jg9oW@j=XK<-Z!vDcP~=Yz3s$nINC#N<~>Mu zH~A;5tC=$Q0LegoFV-VGYxYqMBE+rCJn29ACW=142zGFD0d)sxoVJ07=g9G5gKyc| z;73IQ^b&kqmlElpNJ8A%CcqM2g48>LX8J(_6gkxp>UG(jgKN8^gk<;A`t4^y^1p_3 zyO0XqQj#r)=;%-$>dJ>;R<;8)w2cSoPSs9dPRdc^dW*TCbJy`(-qEcjgTiB=ghXo7 zDsK%^(@Tx;Gzim){#Xz@dx!@Gaaz@8-kY`s!2N=-s`SelW?OAMRUT5};ng>yv#^?;$opQ-8k(YFJdy4F0I)vdJB5S8KS5cF4tuFb^vPacxz?Ha*_=%)j_Dzn; z*LpH55FV&?1YF>rGL@qKL#+ze5HE9$$=sipAk|AzW{823VW}9%1E@=>gr+&~YSG~O zER5hD2gE(XBV0PbOmL5p`-qny^&U^db-GWb%(<6=TPQf)>X)2jK#%gYx{td9lOWsG zcX5UDIyyw&cOJ-S%M5R0+jyLnKZ7%np?NrTo^OOT5cwZ&4m6y#h2u8i>ArlG$EQ5P z9$wCIL2_-Av#s9EHeF1pMz`yHBw`NY2v-M!3>BH_T?4Rc@&&;}J(#%Lk}vfxl6p!l z65z$R^6QQh`)4tQG8YEfv-%G5eUa1iiRyf=mjCm7F1sS6m-zUd4_gy#I?NMXFNYx2 zMYLYBrzBfC7Yx-|3xQwbBR&IpOCauZo`U;UD%?h$6n?(BvImT6{V#=Mu=cfV;czAc%v8nTm0G$fRs6Bc&6vM z0k;wuv4iw3o*q>8HD)OCuFX1KIlKN#%C>$yv52aromBw7fK<4dmuRjr z?`Zn8<7pDTXpw*RlbFBoG$mbu31dB#-Bl$#I2X&&hr@*>laMM(SO%Va4I#Uxd9o@V zx_B)WlifgSEGs+p?q(x2-hF;7a@-;Mc2oU~wZyMF=I3+M-_JPBeFTm#WYK5VLtfMX zB`$aHk370cdT&Z%<`VmTcyT{UaeciV4)6@Q#J==XnY=l60JkYQmB-_g7a|@iqVdF4 zHk9ExSv+R~oHI0t<*~Gs()>j2vjpAo66Bt~rgow6cu6~^+GzKIM{ZXKdZx6*@k zX5>OBNS&njY~O2&!CK}%Nrt#0ksj`G)~S4r!GR|myVTKH_*(@39%VV~=Hb_?92cZo z5w^;@OXUm9v8{-ThbsgT>*UWDXlJBbSJlksq}j$`onu$;c2``y(yi4xtz)?($wkXF zRoz`Y7=Uk`o98sY`iU6|ruR9BnaY2*OvF*}NFLjw+<77*$!6EfN#Y z$n@QZV-fJ8xuu8NkXIi+M^w(-()vyD+>#~Nk-X;I(oA9AElk!!*oYsmaMoeqAf+*p z_irgW5~bj2Q%j-t0HN=3mB&`So(1_GTjVUHUaKBNDY%K}0e2I4%@DZF6F8O)oX15C zwT-OL^M%4sU|kH0W7wYgfhx^L2uY5zT!_PgSmifxD%};GuKcHRh#9d1MfTN1kY(b< zq_IEE$F=ylK8kDaIk+?M2{z+$^>d@^{5*tcD#>f3KGM>{7kiuXB|-9c>)d~UF7zhT z_+I&1cD}cJT|>*M9*$2FMjPDcz=`aDRb-7{(Xvewy5WgY`}yE|r%Fr*(j7#5?6-EP zHSJD2dy_#lx>Jz@PVXSMI{{Akn%z%Zo$kN~BT%WD>`9h_z|>MXr>*Bq$v@C*mFg|G z31nonZ&iNpqDq10IMM7N>6g%V!)|=b@iHMMgm|LmI*D_D`h$$b$H{==Qrk<;ek$O}z$opb&4OW5cSuxke z6ce{hUC z`?eIt^`1t&oI-r?cX1)MPu{%T_-YOecp@V)@5{h!- zH2JN#cG zua()Jxo#H4x0Z#cJ&B-sj+?~U+*Keq9Un<_zi39I0(@XC`qj0PFVkrlBuW=Ri42|X z4)9h#W3}|dlNZNT9T=va5$bD@gVu z6r_6UJzEI(^EhsX6-Mhv>>=D2gj?WoPYaSiFvA_BzU3J3F z*Gz!0@e4i$xqP~TfnlQF$r;jRx5t4TGcaKk({rJyTOq^qMR7t}{W(tMH&G7b$@c*9 zWz+jup1{Xm5666`xI@=+kzA{ z*J`NlXcZn?KWn5oxzi9bN9Ji*Lozc@PQj4O)7%ajnfrQ~t?o3Lhek4U;5FdxD+&G? z5AT7OzLV#HgVu}PYP_;y)@&49zL6=Yei^s2^1@;rPkKx7Ma^$nWSt^QiJWeb&+>|b z`nu!4L{xqor0m;rD=JU;>Vf8@aWGQW%eXbPw_y!fU@Y;>T8Y`$)PrWH>n-v`V|KLQ z{K!ku6`gYobRoo>wv19m$qs5{SiKtwZWUJW#&xpcT3C}p^QLUG!0ZWPw3`moB3Zp# ze3UGn7jHGibHs-qZ-^w->5ceqmQawIr}u0H^F5|cXmBP%#pEP~z^@T?r^*TM5cGuf z!=~C5Mqs=rKrgSxvdMhl4aCe~ex)wL$sTi-VeW63dwa}ytTP&P6Iwe4>7=5|G*_?E z6^n2yg#0LyNyRa5v#7}U{`{g5!Ay>iEk0fm6KW^JVR%bBC`|)uUn2P;zTN&c-3JpK zIpsE`kEs5u6I+k(lhf49YH2yJrpreh%@@A3ff)n(%HEIMP{SR6)*s^@6_b%?;zsEX9}NPXj5 zS>2v!MWnToth;KqrH_drU~TBvIq^a{F$ZNPhYaego{_}mbdKAu8<&=sr1cNfG^n$e0&DH#=u*=@9Zk@b3FKa27b7K zAH>tj;=2~9uS@f;s@%q)wh&bIs>+RdwVf|`nXX@SPSu9*YBe;iO;)J(tvtA@%xcbS z_40ky#;SHGHPc+dqd3m)fJu_dEvot(m?YrBMW>Z`1N#tHunI~zJF28{;i61+_QO^I z$qa+3W86sCyWx5q?**wR7aIQUvd3se>o0XW{^hdAXr=2tft4ga67QumRhq>*B;&)4 z);AYDkZW2A1*t-wHu5eDlJi?D=FK#=vHV*h;jC8^O~X73Eh|8cs~z=OlK57#yyOrbFZV(0b zeO4aBqNKY1rrp(2%sxQEVf6*l?^Nn;6G?HB5GJG_Fe&ykdc#Do9Ta~i=Yh6w$Uads zz{b;1_tV0G+XA~A^!j?w^u6q!jd?SG&E6O|X$)k<-qj(ZT21C)Yl_c#liGAj0hQ!{ zg|;da4b1ADBjc0J%EnDs*pz8E~l}A-=Y3N+cr}@Pob?PUE zgxY*lS65bkgnK{24A=2U`v=KYwz8V$3H=P{G47!l^gEKEzi*Iy*FYEPJt8TQj&W7y za#`d~?(7)(A&<-*erwZuRqdV2<4Cu63|8&I_GU)Nc$~pA7xXx{Q4D&72i>Rg?J9M9 zOf!jboJ&);=OT4--x6cqp!;djVK}#P8U3|*x-Y0`GTD6P>z2)BvTuO%mum*VkLs)K z)VTDT=j0Ae9FIG%`F=wBSpp^y*3R*GC=a(@POoVR}f>Fw8n91wq-l79XLR|4>I1HyA$|z zy~R7>dEaCOy)P6i&FA^>HR0aG%K`1{aq5dIUhl0$0*4}PI0&!$VMRH%EEB1lj zi3zfDSAl3y;+N6fy-}ydzkbLoNF6+EsJBu^b@LU_Mu2Ap9&vrd!*+4^Dsq{KUr7jS zU=w#awnwxIVloEt(*%Ftq8ue_>j+q0J! zf}uyFTC)SmZTXdMqlwtpyLXlA>fHEwo}Fk1$_MH7c^Q9mYZh$mas|duw9v$fL?b?1 zzFh{ZwXp1q*J&}{)CB?emaQ! zDylh(8f8(@TIX_d%?&{zw+oN3YHc&&WMrrQ=Y{njo>rxEKH6axQzjta#d5)V^Z{5afo{h`GkVZc=ucPh)|t- z?!UzPYsG92cz)mKdU@(CcdP4ABfH;6P*@Lx#e#vhnZ|>(*CkPn@q5i@Ms?Pm>RoH~ zW3u^q2Hk<2{5*=+L<^l%+4e7dgij`8(Z{YA8G0Cb;@U-8*zPaOPj?NOu8ep$$}@9| z8=}Znic}6?{z{y~1IgiOt_=pr_`|6lTHJepp!7)*wR(3C%EsHy@0||T?pQtQW7Re* zn=)O?$7QcGfZ<3)p3w6mHsRuK8|>i*@Ce6f&nUT8xp9yxTZFc`-v`bW!~q_HTOYrM zLDil>#9zj_E+YZh(gUmtk{q&(JFTmCtG7$Bkh!jF+8>6`qesZs$YQv%atB+wa-R{Y zYQQU^gA=6sVoZWd=CFDY3Zd?$0C`1_oJEN5-+8+6p2D=~1FvcBDO@9C&#qRar@8S^ zbUR6cah}NXAbExnIhm&%`5GKLJi#aa=?~1RTH<;}@>$N;yOYU*%$H;%BSsXydUp}N zqTlt!sGdjI#nbwO4z|q}-bmlX8>VfpKMn>lXW8yUxo0VqeEsq|uOeFuV|TI0zR27k zMo0(A2MGnKdo&k#DJe1|pn`tEN=Kt_4FEGhSpy4ejumM>?-Q@J#p@u? z>-QkJoAKH~@BU&yJCBD!soOYWoyoy?y{-@~o6ePK_qhw{=(_iF??T!a{YJUAa^ED< z=Uip5cQ*mhw5v+?Lw5p7eUSC(74m7_uI4|vDIe}$&{%X&gV>UF(aL0SSc!9E7q z>e-1B)7+CVZ{q8B6{Ae)ERf85i}KZ;GIx7^LF>qF%T=Q1+=-r^?BMP}4y+SQRIBN> zh&Y*rrn&8v$9|Na{ZjTOF+GTA-6k5jgDUiuQKp1w_|Fx3KiQ-1HtfM#;}U+AkDr0! zZlJyjd-!HNZ!1$U=^E8>u^gM2vYEBz?x5+c`Fi)B1Un^Hun6*BuPd!{JHman^{+va zvM16FJ=pqc_}qv{)@^}q8kdnK_WB1fRnuv?%%#|;Amux=3RGBkEBed&)0MvZou&q& zo7Ku-yO>{5dfwPKx+nMzAERQyWw_P!4y$5r=4o>moCo@ms_QS6&6i*gRSsr_=vz8} z5D{$$Rjv*(({##Gt%+HQXeA}$HTn1PzRVO`JEchLoJ_BCs}L^A>IOEJE&ZE~Wh2jA z+%K;uexMAn;1(5#@p8F$2};3_L`!a*Y0Fd#+0ANY?lyqJ=Zj41<{$#Ay9?rV`V5xTZwv>m$2HqTc+n@)q(47 zIZ)@Kd*%M&)6f$nw3~){F{8hqtl^ZGjG~6~q;TA;JY|hHQP@qOM1`-?DIt@73X+f6 z9NJ8tme)UWKBMKe*I4zYG@hseovZP7ksv>2G!D@uqwxY>qHLb#dZ^mCYBlx2m&52- z=)GKL1hf@USBQvF=KswnvSVe3#+$Qt_`fb%HH1fn;A(lw2n*olDwQKT^biq#;QL2g z$+(}VWqnhSJl(RsiMq`j;%*G!za?qB%bVm}NaUI15c?qUNMoaHk1X^*-lJM2)ruu4 zW3G?onRTmKOu|nCKox6tD^X^ua7_3}-)i4LD9<~#McQNx0;%Q#Tslp3?VY0<)m~MbZHH@!P zF7o}pWzb1Dj1u=+JHP<>ate1!a@S7va$8@Pp{gp8|NHh>L!Bg4cN5RJxMpgmh$)rl zRFah!x=Rid>Vn$;jl~U;uBWjmjcDw=h6+;!wDLyD@fS}*N!T1jb+38eqvaBp=~FrEd<$F^psc(QS@K5IMKf z-X%hZh)_-OUr$=%WVxbh_maePr4I6((^1^ritC}c>?wJgY$&J8QQYvfNEE19XOgkF z@K}GL}d6?%p9_rK~;n}@@UoF;OtZbKV-h@0{3im3T)nGe=&5ZV8#PUW2lrwEt1 zQA=XY9v1g|ZotXrU{yS)S?AG|ZbvveK)+&yyOks+M2`lSg)bJjUcj4J>YAgULN`l4 zC2n8J9i0w2D~z`Cl9%~!fYzoKvq|+*v~F)V)?Ngb-B^1Ub%BO~%^**N6FlyRojIpE*Ns3&~ve~+YBPjSrLv7p zd+qB5k4Hv(Gvs>{O`IC=4+4H#z`57HTI}7#B8OeJ`o+9h4okY8q}cVLr9!j%wXZ*k z@NvMkt7Kx2KaOT?A!!wdta=RQ!!gJx4Rc)!z zKe^U;3H^3PeXd&u-I5oQ92<1?YhQh#Gt0_L+f}TO@11UCm?E?GHso*XEy>P(VJUzP z72CS;WDq4|1W=R=_tgNn*A(v@BQ*@fgW9`+IFegHT2n_no<%h`+`?86o?CpTIR#4#kas{Ep=vs#EKL46_)XJrRx z<$tQ!`_W0zhfuOJ5EX*ZX{_xkJ6G|EXoPsZqDvA3rObk4_97NU$QNgQ6X&q1QAQkW zSG5zU2bwTni6T4|eYv7{G*SBHM1M@#&gCCLrxjh2*j4=Z$>qObUIBd)I~14vKhziZ zIVakcpzq^e)Gav1rE;_dTCr9!JX>$owd}4epzE!eqkRnL^%c+@DrSU_=|&8dqhb#C zG?<3SNf(VaK4yn3jfm=ISsD@Nb$v`}mQSIN>6hU%slef}@%79F&ABh>%uBYSaldon z?(mv_LUX6TzoI441{);`JDB9d7+k2{n8o-~zb~qU@Vi~~`%(0(T14@qXXfp0xpleN z6+d=}6}2)-`~3v7cNI_Lt!2!PZkrRL%7<=nJG-k`md&}V_@dM8GT<@XIR}xY55;-) zGa;;@zv0i=4_ASfx#d%=OYsXo!=J%n^;cEqzEX6H`^2I>bTiR!=70rYzmS_gm`h3Z zUQ^t3u!J4%Zv4cAsPsb6oE4TAlKiG6%Lpe)C>8D(KQ;9aj^EF?3PN;f;+uabWpm7( z^_wv{;1R=(d!iQ_(QdAvt#Fho>oS?_W|76P`{lui-DtH_HN`J;&5k;=l<11Vh!%A) zqw$zVOKMizU?R_CPHbbtcV&@FG4jFW=&VASm0OcG?$HbJzvcrl_ zsqdVH*RwYUsw22!qRgE%X9a!Irk~4OH8qvDZu+jgsOhWn;-=5b+cbS#-nMB;dAp`} z%hzgpyS$|7jq>(Q3sk95DS*GX=czWJsJyJ{wU+vvi`CqF%5cu-ev_a0Y9ZBLFGTTA z+Ha|Q*wUlQvZnY?yjRt9Lo<>1!fexG8}CMwB=3Y+HU>c%X>Xm$yoE9ZGvK zftT{4L>GlC6b=%DSfOxd5Kgr2O=z$}MWYA}QmAV+p)C|z*^5vQg$4?HeL~oa?HP{vlIkMXM3E#NqtH4p6FSY}B;PR#nI#Wa$mAQY zkjb|@A(QVq6^&>&dq%_^srC`9g0z;|wO-yjDH2P0pQQX~MI@y;S_dd1r8!`M_!Oav z`v90kw;c(+NvOP2V$ijO8x`AiJ3>z>RCEKOhZR~^kpK0N+X>RrTPZfF*dVdp5W>?1 zTP&;#6e<*@vn*~;LMJIyG>MSDck^z3fI?TSqBYsBjD+L$+FMyWNTK3G32k8^m5Ck- z-7nxl0^ZhuhY@P0klAk)y_-alxc#b-#eGl6Y`Pn3W7u@O441Jf+Q_CoNNbsGNz`Y) zUh+B5dTBv;1vD(@&8E+Yb~8IB6Wh&()q{F1E+tf@kd@yGg-ljcO!!{0V-zyE4mM!P zIy@7%J0YL{4*lXx4&TD{p;A(MFJpM*@}UlcM| z2s3e?6EZEfl@`&_Mj2PQ(JQi^6qz0Q#Tm+n*vP+2mrJ3M)#VY<&gycfUfW5Ru?m?k zuAVP85aH_%uiAnE)dZZvshph>jyqDi+@=lk8tIK;DX)UuYsiyc@DHh9H zOnni)K^Gt^?@HcsnY_;_l$BTbUf#P2#q!Qk7UTtc^BVn z@;2tltL^8w$5W)W%(f)XY0s6ni{#x18rh;YQhcK7YpD2isfOeF3YoCFnm4hTHkGwj z$eM*e|B!4*I#rcJFM~LQ&=_LTwc{N15)&ibUmZg_;Hvy4g}CRgFUHZ%3$_P^_J$n>wu4< zc-sl&AcV4^N2DCRDFjrCjetahf*vA>1;xsFHq@LT9waeDK@tuH6gzfA)JRdpLO_vb ziHe9~i4A8x#8?TU=6jxZW^ebBfZrc~US?WuKo>EqQWkuM1{VTwxEm?Syz)Ev?dnHs!OE^^OeUu zx=g2&=YmFcd2rxHP@Y4|_35~?kb)D)D0w&2rs>|!bOWvH45m|qZP^U2Lpt~xN7Cja z@OUvF8?rSY$5aER`ZDEXsxwn5OtnP{7T#fu9c)G9E>cX(RpBL!w$eVPW)tN*rYfOY za9|c5|G=Y|px06{K_I~da<3iMlTcP&DnB>XCdA$=9O^Ze>c0 z!SY}V)trJ9f~;fnopRrqNR4G~gJA2iNM9kai;+5kxvAQOXEC=4TXlElVzXTEVbYWQ ze&dj8D*3_Lq}N%e=TnN-#1x3wuShi`<*%7Kcmh(NFjenFq~1je{rGI+NO@9Aq|9}@ zCBC#r#5%md&vg()3v~5;57RnQRN@;>GdjKCa$08`D7*c55&0NrxP{zjGmaa?stEB> zqQ)$yQt9!7Bo70!I*O?@=5>)gdVB^`(v>u0N}73!l(PB$^$YTN2EVFg>Q6S`JxuvX z?{lW=k=}<)Nt@fkl(Y<9x2pq*)$zRLNQtZb^N<)LJ;4|&wK2X%S#_xtVd;ZbbBwWx z#yAx;WJr*fF&$56CDIFALp~B|k6=n98^ZE`gRMqF%F$9z7wf{5G=vPKPyyEpPg4Qq zsEs(!_sH`@ECawjJD&~QJxFT}KSxTm>94i%CuqZ97nEBHWhpB0UFoI#F)2?M%1(7I zCv6G7@|hCL-^`TM=`~C>qP=-7FSKgSnqj%qPlN=P8fGyi4SWz%kYnD19v9n3fgP)U zML8;eb~Q{PuGHaQ$Q2F802{qqDRqkX(@V961B9{^mH1|RDgQvq_XuTYINO3JXe&L| zYfPij4u`y@NbA1(c1f|JMwpU$>Wzd<3ht-AQr?yg_Cl7oDMadQrVe&RDu*eN{bZy> z_PZVs*~=4TPlaf(N*HC;rBYPl+d?HBs~n*0pY7AWhEC)zOutnZQg1=oDo}zg)y-*Z zUfUbOHEm2Qrkm;X=brp>q`}WeS@f6|@^a&9r+p1z952g9TG!vr8gu*ol+;+cpBI;5 zl$|NKu;zdOq_~vW;zvW65_|MxO4?|*cwRfC#75VGI_fuzR*Bc|-MW6q3TG)Q@jamx z&|Nn#skLAFNo-_-F@-0metB)L=D3on@M(~28B^lT4>KiGjzvthVvXL(l+(w4N@ZQ`ujxM%7hy2S6^!MagPdLPpakAXeUaW3L4UTNUU%?o}BTsANe$7 zh?K&V%((yBi&O*3T`4Kn@E)X4^McQE2Y(;aNx_1Jfcb{djoDJyGL?HOQqMCbHh4lq z-bK%qa_LRyvt0VD*-Xjoeg;!M4lYwAkF>93>NooOg-prNb2d{+`J6>(q2Mw;cBVmx zx&;gHcsd_j_>tm0Rj4P?;#j6l6w!+iVugQWNQn-=GnGQG{}Cy8dK(V2Qhqr#+rjdN zlyV!(8wA_3{7dFuPTQ?!>ez3QTF#Wz^irmhiE|HA;+Mrpp`S=6wvezV}5g1l=4 zNBX}w&P1lfJI-WEf`yS%N?RSzl(d6Prjn_74=E+R_Dl(G3#J4&RZ5Bb?~e}d?@T3& z{!EFi6-){4PNoF+9VsR5My7=CTBc-m=Xs_i-h4vfD8crlET+VV2T3Wp9mSMjbU_N&*uSY?Ta8K2!A^^ux%`Os@_V@0 zza5_kx54MZa;5ecHm=m(@NLSNWPTxxPAp4cw&CpoVdk(|y&^E*q;Lx!Uf*Esa~6Vg z=7BuozXTk)Bf6+2PIAs%p2*a~-OChirn9`KpYR3t8;hj_knvjBCCB<{$fmgJp~UyF zE-y_&m!Qj$IhUCR8seoU8SVYlel)f(jGi~9*XX%ru)-T6Z9Q$0QNW|(bGM*mwJE_m zJW_la0`)=s2|mdec6Y`h@^v0~)&r)==bj0>!C8Xz+DINuBgVe0`I)jV{Hu_GjNjj?S#uBoRQ{SwPbOkG-<)P1nLB!1epq1 z8+>iEtX)l+NJ}Hz)MDq56&$kSbR5MZXY-y_5$IP8947Du4wasgAcE>#m+FiSed&acBFRb z4iHUz*eL|u28u)}wZ>?ucx{c#Z>1mDyATLCH9$K)LW6t=-~knV3?D}mY3iVzFsgZ7ZU647;$;?D%b;JT>eR&ro=tqVyRvHNUFB)T0syA2P430a~;w?hE zcg1=Oobg5qcPv9l`ywog)6MY7`1_2erQ|!7jMOE5luRWDDfylyeRK&r6;y08Pvr6A zPe9FPKJGQWTl|hqE-5)F*N?1QbXGuJqCu|WGddWQOVo3ol;ahP!RZQ|Y~*oMNZm%r;LgHeu@Bzu)Hh$|{aA`dz#Fb%Ky(AB%Mp1K zF^#StOkz}YFSM8I;gciZ=3!T!lb^@@9I4bkdA;!Ap@E;md|g{D0H5jPpT+zPJSSAr3OvFKDd$%-ivDOYJ-NA9EwQen~sl zDQ$QX3Y_t6^M(d+A-xMDy9)iD)U#X^SP7DUM`2DULOzaSg|SeMZ8`V&QL8W9k4hH< zNzs)knn>um*bk)l1X;7M1ri=A;o*wI4{od@nSOvp2a=)tV6%OQZ{6%xD3Lq9=OvB0 zW24Rf9Qz~|AoVa9C+M^NyP9ne~ z1mON7)EJ`9T;4ohi7)$-VmIJp(#m?VkYrpQ6cLL6jZLR#2Vdz7D@?nOJ5NcuNHQlf z^HL|%DmodWO2K~GY?M^*P;FK-}e z65I~^sHdQ-u*6u34`fPwQ;R*ddI1Hnu?p=l?;2+=MW3O_af^7Z9*H5;)nO7zJOwyU zYr{@Sd<1|W7i==Y@(5-ckX7VImJ4tR0WKl{8W47=z~XRpT!aNJtmr(}_2%sIBuvcg zIeb7l(veT{c&1u8VPiKjvllXPBB*2@h0KeXi3F~VX8=%6fY>Nz9*fLDdB;j7=3R2E zOcD~2ZwyTU$VJp_%Mn~eEs#iKBbrG27FV_TJqd`hx%1$lT>;5KG#*eJ&YfYQ{H3-bBEY4d68ZbRAfVx}vBK2Zm_y z8TXi%+!i2N0g0BeM9k7-T1AV{ zpxs{cD7WBdr$BnmmQF#q#O*czT^J`b7y`x?xi+6gLAGI`+S_v`F;JH_F2!7WcbbU3 zOSi~fFjG2v5;yP-Vfabc(Z&aC@Fl+LIcSJ(jDcc&5YP?{z{Ex$vMpdgvVf&JLoLDd zD-jQ1d>E{4v`KUe;yD@K@n=ETf_3$c1-B6xx7 zFbC>0zKzd@R?|vPV2RrqiLvjRLeDc>an`VWHkZH=G@_%Cs#tfoV?`;x0mZbUOI5PZ z)KuL`=4W>_CgFhk1p8#XAvNw%x?S!&PB$wCuaRp<;%|@@gX&B*7ga@-w_$-5DrBG* zXY~njH(iGK<7&7U3>Sb^$HRuqM|gGa9f;z4BZ_yd0TQT}iIBu|=vSk6+;9ly(=f*- z!ff3}7&G-t0gYCPoy4;~qVQud3oxrEB|iK11a_GurB_x;eD5ZfP2c1xdoi)> zt?gi;XD9cvq+la_i0U~m1gT~vqPz+e%?fTXPbQI^zDZo&D>5OkqkOy8#VW=tEA-S+ zb_Sa_`0&T(DF=wkdq-yG-74P^b&X`^H9{$dhNReyDC&WXm!-%bnV2^LMd(?QVmy?& zXXLcJY$@s-IV$f#6s54}L=<&Hh9yNEBVF?RIRm!Fx+A-Lq;+0P$?k;t!Lz`C8QEL^ zPIIJ z{F&QKw1$H`Qszwj+Ncl*09{kGSOXHoL>X0we-6U@H$bU|m6nir^ltoWd6HGs%L-;_vdrI&2DWLec^b3h*5gxb;oJg$?7$D zg|XTs02l$tp$AE(1&7lhJF#euFGc+JaatAq6<$Mifu1yTsMEV{;WF5fJw+3(0F_h_ zWoEKETW3;~-;j)VI$XY$mCqjw^d~&Y<)h|q!$fbm^~gq?50xy*#ggQ>`ay+*%8wh; z)yrUj53AvqiTRI6{y|iwlaEe;t6b)TfmpYCs0f^WExqoIRC700tuaW+jliw3S<+L) zrFS#bSHZ9ngwK8&v88#ywDM+>SOPei2F{f!B;imrjYTtcQ7`xiC%2~P78YHqi?Bql z=N@)X^jgvZ9qdcr_yfO~!Uh>?s==rX`zPd}E{ma$ReUsPSkdo$2#|W1cY)taIE>;Wl6y-JVH$g;f{h zTkVEqwjL!2M($>?dWkMewu+ZDX4w$G7GyOMN9w|ATzw;jJy0#~>dOXpCndh0^CTYP z$Nrmu1aB$849-p^Zb210TdR1Xpg-OoeCvhMRXqlfKlBl)F13mWr;_tcSc)JKz67+l zv9O@(OTk`+2P^sC$bl;ay}bv59z-dKu=4j+8u>L?AH57=c$@-ypX#rsk)1n5b_EVh15GiGt2avBiP zd{yj6oH)3ux9BhrvRK6r;=zjEgI_sMmxGp7{1yUdE84sn;4~3<0%vsg%Rh+R6)*uI z!(+8eeaoO$AHk54J4m*?Q76tg`^`!SU5;4qL^=Vcv_gv1D=n}DFB~Q&x3zo64qZW)`M9#vIq!5M^-Rv;5p;l?3Fn;ixVSBix61F@Nk^1Qcwg%Bt}o3y zTOp$KL4JuS?Y>$B+)n!?cv#VH@N5Wfx`hwO_YCkg(+}yB3hr?FBq<((V$&yW0VbFK z(bs%P%;v<@2m7a3MW?biVO7q}E^`5SF08G-7eIDOYu%!cS@bT8JRf$~k8_vebttaQ zeJ3#&YNA+QtZM6yn&Htd0|C3n0W%j6#otMUyVQUj;XoEv9pMtp9T&p;r?u)4)PA5k zT&8|z!bSarvNWuX8c>^Qo`SNZtRze)uF$QK3qMt{Bh=&Y4^UI;QBu<_as)u^-{A5t z@y|(o`FC+MA3{+9D|EmPr>H=l=RhVZdZ}(`GcZY^%1W((0@QSu4Dha0bS1l0Z6X1+ zgLZIKz7eXahe1s+wcgKi21MG=kha#F2QAvSb%)*sRV$&sReUubaAqcc6{QKFL0#&? zw*x#$BtZgnNv|OUvQHs80%5CoCOq7V_9pJh2DgWc`z4aZed}8)sq%^2khld^Tn)i# zZy7{C1!wZ9YR=2CrbT$}|3$i#LmJo0wd4yx4a$|GP2^%m2FOxX4ilK(;06?I8SO(kAb)tg6o=rU>2N24F|k^3!w|D*pFMqWetgN59}>H=Q7ExOk?II z#%~uoR6;@}iBt|k0Q(qCh2sWpoyLO|ZG&Icmk7FcPlfpm<1IjeHEv`y$ep3!zf~~5 z<8O32I%)L_Ol2^e2&OQbuQ7)Zb3HL}8xAfPOC{Ps44&GhdIDF>vrExS4cD_N=$#sA zl2v>&QdV>-pCyL)6*LXfnJ&W)L>f<^f~rj-<83%;ABWihSd9T6U1L&d8 zhFG#IK{=8(?_UA2Ekf*lsGy7Fwf*5u{!0vZT?d8KE zWd@5|*G@n+S<#;{^ofr6Sr$-zw4!kG6G#mXwai4+SrFqWkW~`_qQ=q4=aT{3t(gsH z@mW^4gw~f53GV`}pT9|GRnb1D^ z5J_wWh+W=URQ*^~#cBZ*ONGLsY6eanLNQJqB9K&P*Eren4%sJ#Y!W3qm1Ma;&c1~h zg;ltps~$$ayvZ8-dju+|KlKlqv^_zC;BKxFNackAvJCsH8F+rF;XF3vu&lsHwIcN+ zH7f4A;?hChEi##J8F?}9N1!m2$?c*Ev~dWTNg9P!IF_!x&}@TW1fi;@(*^g?WU@eJGm>_7Cqcl`YB8h` z>hoEIm;xbaiM{MSz)TMax(_S{s#?oXc)iBQk#akv{a=kSj$KWqx(r({#F17pq4CZE z9{L>azp{%oCQchX1B|Tbi%04R`c!CV2U%E9CA0iu3w@^*?SZMI7=`DW@l;FH{F|7A z(L*W`2B}_Dx(;WQTR z*)2qnyELb;G8yMhPzN$1sb*>+w1$T)Rd2H{!syarU0i@O8S^45IsyJ~exiuP5`P`a=RmvHvO_-I92CzB;zaR^=TN&MI=2vbm1 zmIQ#}dNOX0lxZ-*ngfC!dpj7Ql^~Sa0=D*ajq{e^T!IIjI?pU2&B-Hi&NetnY7ucp z5}>f^OsjZ5U&ciH#1U2)gw6)Rr!FHxON}thDy~Lbv!Vy^t2x|i5Gp0gqErKEjGf4~ zdH)L7oNN{2w2zwHN6Lz}#jo9- znFUo`1;ee=l3%SaFL4HthrmMF{P|9pErVcBz{B92yVToEz-u|DPBv2n+|T+M9HhX+ z`7_Z9>@}q6+$Qrd9&l?ZMjt4F;l3S--w`K%8fofoay1CmCZF#m-;v}eX!0vWi(x{3 zD6_;vUe&f?%g82a{SrsoAAGEVx}4S0N>g}VDExz)O|0mC-f!aeR*ON#Xj+}yr8>L} z4^Fqw4rwuH(`g$hR%DFb@h;3fAHNQ*#Cw^`-OTV_=CTY>Gm*({S-8yQMkEt2b9s;b z#oM2_m$^)#WQA3@FSwt?&m*x$Bf}-{&XBlcF8T+p{p%9nOZ@XGl&2Mj8LL)+##!-7 z>w{ueT7Z+YEdWu!Gx|P=@E>rvgX0I82zxc0w`sCCl2Zb+ z7f6I_nL;E&BHGX$2s~Z`<7~^}BEt!kAsrlW?qh$+=}ic!w`V0-S1OalY8rW8T%vYf ziPnOj`i}8@tc_^I8DQ zjU48ZLqXLu(iCsRgT8Y>litU$cpAXi{e=EicY}tBpIU)}Jz66_3*^W;EBeDhiK#9% z0yTuKLiKS=Jm(ea2mIJaYJ{hRTZ(Y|7wVvwKiVMCHL&*CTs0ulN+Rt61VmgeNbigG zTQyP@irK~<(nu}U2Mls&66r;a^rRr&kB7WFv`+0%3Kx7`P;#DOGnz9!K^%_oWD zN#Z(9;(Z};E*>yV?I2f27GDL;=)lsrr-r zZv5C5X%$vY!F5ipNc#``g0|B>7Xk)!;WAFVR*8oG5NbeeC3-o*3#)=w@!0(s3@_JW zov5*>(c2$OWf5x%u(&MLlA zxK7qwq3JgWf!PYG)wLRjiZ%ldGD+!NolA39A!%o7N>efa5lU_1l$K~pMCziEDEga3 zI*8X5V1I*Ee7e}IQ@SV(_MF3L_WR&cXoO@RCC+AzgUiO=#C!pE#@LRT&F4UX$F)+g ze+8Rdg(v$VLOS=6OFwtBtn0j%1ia#D7;>#>5@v`VGdI<2J+-s|eA|LAvMNA~xN_~| zQhwVZ?*fBbZMgH>c{sX z-3)S-Yc8)8DJI9I_~uK|nUi#3u`I=5u?%5>4nXFOU&aM{Tywb$y+E5Q6W$AyKk2*| zxDlxKSzre^C_OFoBD?P3j&OD?A)<-nJ?@cj(DPpu&Qg&Kam zRh)yA6&-ELoFb;QHfbZs006_0i8}al;)# z_9+D3fggFl#hdzw^0EhoH}%nv9!H*M)6S&F9Y1=C#{c{sh_!^TyyW7>*)ngO#b>u) zZ4Wk}C9BM;5RPXe_-@jc8E`*F2|JmKJ|95_FZwLQU+rUSz)6*e=PFe#Eq#~z7$Jsg zip;ovBp=tWwWA;D$Mvg55GDEv6GuOrxzvwR$MyS&xoN@Isb4Dfy9p%ir<;g=uL9C4 zUVsNHdMAFRsveWfTP5>*uAZ{0mP+Q8k~x`>tg1&P(}L1g^vw9=tinR?%NPB!cG*rV zzZPPkRY{j!q1K^7v0Tv^gy43KaQ&AMZiru0>L5sn8pDtRB=shK?ERQu0TP>Su7DzW z+ceS3P$YcZ)6(UtXzq`^}2(gk(9Nox;v7-Bn3)c@UGz>g~sXx z}tqJ$nX4fF$ zR$AWPU_lXIg^016*xkRUS0-om)Bvd(KuF@AkOG$GD;$&*Eqh&j=g0_S<%O2yz!L))7|q@9~%lXiSq8-tWw|gEXB@M zoF1eGGO#Q0U5Kn|d=S-DKaPn*WT0@Ed6KnDz4dAVOjRFN)8F_0py{?vz-knKN>$|m z1))DLbQou-R~XIxLMPhGpC9=14K=SHYOD@I47&o|6Z)aK(hqILgB5)fzi_5s0mo{+ z7i0x~JK;+;JVzy56eREq3144rbm%@#xH*L5*^@Jao{$9gzEd;mGN(fBU{Kk~8_Ey8R> zdqW;soJ$&+A@k){5nFhPZ`B29+)GU@=WarIvdWgIb(hKq3$+%AjPw?h4=uJ8rS|jK zCua8u{gE%a_6)anUf%hqtG z^fcw_jJH5+H~bc2Y!G5^;lYZ&fnT{?ZX@l9%jJgIVoztDc?MXhdkvra8QuL#n;Jg2 z(nM^x3yLm=-yH9M{s`l1`8tf5ziUEd-){zb5^-kS-L`Gx4kLMj=Vfa7hg`q%t(A9S8vJ3p6^E zL8BTe=qKaXbH#FhJjxZzn6thB?pnpJnk2%5c0t(NJW<1%kW8Jc4?>{s-ZNXj>3tOdWu%czO-NiwJKFD z#b}kPG5(?@wpPPvwr*O!uvN^@bFF9^e&OOnK^xsd6V;AJc$<*&a<8yznpM096W6?} zAVEt&QGvCPTA=q*>?MSL2Qbk4W?b?pGXL>2gcUD2mK2*9%vna?a}bWGVw4D(CrM^3 z$rNca)2-qgkg}pz;}?wYCuB12bhwp}JqdXMAq%Q*6FYIo7dC=m;--0)0Zdo-uc%wj z&s0F=P2feh$HRwU{BqVmeX${l@!%5>D->e;MS)-NtBKtdC-$UEY@iVPi5Yqm^n4Oq z2T+?^;bDp!u^$_$yd0SKGvq_l2I^JnJ%vyYXsF!C4rmF%q2+2}q||xnUj({@&_fA* zt%kk{w@xF4Tc`00jN1%GPmO^c!o+Auj1!1aP?aw#altFEH3S)pB9LyR1_ID-t6>TR zhMRftN*8Is_117{DvfYIBNH0o8lBw)jed+@S;>k;ZphmMIsO8aj5hhO0zKp|^m6o3 zSYGx7wdLHrRJ{)0guMbV{zWhyHVCGuQHW!tJ%K@(bEZaWF+#amYm*t1%ruqH%p}~E zh3jP^z4CDCd8N7nY)tJwdJb#%Ld}4+`wxbVW*9)uq3Lf<6N{WNqLpx-BSTJTml zf_?5AB9U1vXow-g&SaM7jq;T^j#algDeiz`^G3PK9!=d#e2<+Yp$_{9KqAsfBcX3! zm%<`lIERIL?=MFpdlO5sy<0vv;kIFZ{&LcKDp}%d2PXXc4uAs6BB4a-P=zjVeYSX6au~K-5;Su?jr-5pRjF92wQ6d{)yz4Gj!u<&*(m?@M?M zN#s1vB3=n$Qx0A9s4kkrqIy9;JV(uy(){z0{KN&EPC)Xya2&!0eob_V6t1fV+zT#T zz=3P;zzt;~xZddk^#zdULnM5x4p$AOt0@|Um7WR^^&nge&Q}HVR6;pM=9Mr{$GmB( z07Wpx&hd@;A$TQ@Me*Zf?|!uXq}Spv+92<0ffx^nzX;Kv5GMeF*No!(rW_>cQqNN) zLp~QL?pNtOb_M(axDLp-4Q#a3YD=TFR0@M*rK-vqp~9#840C)t7i2A=3dV@-X$ z1wTQ}r>M?!FWojb(%T^-mW{OWa5{h^;r6kPgc~IF|CDexM52UaDr3)qT|KoDCNk{C zfgLL|n1qFC)d2#kXC8+HPD8+l1X#caz&C$G@-CEoGoF*tKl@to$vq(fX2hH(J|E61B96$?2)7+e` z(4;61_b|T*68PLS2WWX2Au2r>aMGC0{1@F&b+(G_AP!Ij2cq#nguFfgZ4!`A_0*^W z^z3rp!Oe8#sjr|NB$vMp1fp*R5|x5+7X%aC9Lw$+Zxo9F@3MfLnI}b)aXBE|~-}7o?8q z{Tccbe6RZ^r5rQ#vzhhB%>9h0a0_VSd?S9_&#Z5VH}XvQ?L4|}3IygF{We4#;wdGq z*CPq)0av(Xj&Sp`v29@dGFR87K;1t^h|$Niv`ZlE5 zMP@Xd1EO<)WzD`Gb}WNpz|{76*9(AYrWywP56N@D?%EdB_7 zq*q8q510A_1fH2dU9v*R;%CuIs1!d~xD%b9eGi)rmaQVo^G>co=s^-XHi3|2bv9Wr zaTzQgP{Tn8Qt_;ttXfnaB9(n>yvj<}Zj%Kn%Y@3ob)aH&{ZIgRiqPJ$(b4<>a4r(>QRDy~h^ZTQqcI-Z+G9C>v?YoOob4Kd_4-v&n=n`kMP3g{&c%x{ze&X%zaW zPEpfM&^JGJKWICB1WJP>&0$?Ws@JeUJ$4V)96jB&PCFhz=exBg%Jo1o z*cV_xfYziGQ1i*pC6$wmFJ|y^2n_)H6q81R)VIHL(cx%y1s73q@8BPNY^08hU=+c3 zDy#4p*}n;tPj!^+O7)=5{#vqAR6{<_1MREJE{Aa{@%baxw0F=p!&X8Lj8hlq&=oJ& zc+Ux5eN`!srjoN#(GF+vzLT;)wGgGZlDQPK0()xYXQk9qccTi!-`iw1j1RHGe8EtXQi`o|BPNOX*YTQQ!x4!z0kNhgtj|t8uv^Jcj zz{*f%xWwXry`ct`k&clOal$$d8FdD}@lQ&(ZeAeUkAeU!y#a9CY?Awi%eHVc<{2{%U-;OyaNwM?bSLE8XXG3 zSQ;jFws4ZyagJ^9fSY<|*u!Kf$;v>Dq%r{h|J2CgY3A86w0U@%(46yMG-;V{h)}~4 zLq;8@=3cA=!8#lQZ?GYU9$x*^g7YzY*tj@L#D!Xo>hO~6x=|MrHQ7Z?tpgQ(u3P;# z)Tn;+fOUz)x3cy#EYmyH8`eR0W!L4)rv>?JOZo`<7xjo0FsX2u(w zbKD`{xCXhI$j&Cog0l2pu*SUnbgU<1gz$5QhQloc>~(^5^nd{xVC+N%)XY%u!95WR zH>LyG^YOka|4YV8KZ-Lj)X>wl6X@^zWeG?HbX`KK_sH(qzi2FWlG1+-Jk>FnYzC@A zN0<~FD*%WUFL;@);T1N0TwQh1Pl&-$s^de%WT?v zu%gWP^bsYMI20sjz=u3lKn}f}lsf{aCAF8ZLj@$AOv{mE)sibK+}vk!;IH*1&JW^2sbUk>;nhRWM0e zFQZajrL}JC-Mxds5PD=eb%Y9i`LLUO6MIM=Ib*$oR+U`*^LZgwEtHZ13+u` zNW7PDRFLRrXnD8^Rl~_{c6St#rtK(?Iv@($je2ncd!X^Hl{wqIZc?9bG>-DwYXlap(E!^zE;p7N)3~Br}%zj zSBKryI@no7T|tD<=bFCHfgVvO^dHclED`weRFuIuI+FG*`U3gPD8xyV%!q&do!iHN zt6;4n%R}kQ!G_X8p_H!vG}3#F-=4-#|1)lU-q#7m>t4CEibiRf9R9}}{zU@}hl#94 zIzu5VFaVGmYi0vZ;S~l@$o}t0+qfHIyAq23t{Vf)1)=ry^7IjgLQP5{zHZo31W3|1hmB zw}We}a|>y#tN+x-vY$VMF>b?Q$nbD2MXT8aA`IU2&J`4WafB|ddV+!Xe+*E_C0Mkma9pA)e7 z@kvfAC?fg)X?W_xiI5(R^wCf3aMkpox{sVa8~n+)way6B_@-Nuvmf_XBIv+c`$mW; zZf**1rm}J*HG*Mnd&zoD;Qe@kd?!}?)mvPmhg0CyPiUBW5mSs1dV9Y*vmVu~RBxl) zF2dd(Ht~g8Iqx7DAsbwE=XlOx2T5!89_=7Jq3_8PoPH`iKzpM^4Cb_H84V9$6J#Ki zp(_4?ZVf|i)eDq{a~3bc$XcW5qJo4`)H!=K*VD=$7Sioh5lJUu2QJntArSn(SB|x= z!e`xG<^-L+)gyd20wb~QSB8#M9|0-Um}ct9IT_4E2)u$mLN%p?<6#Bb>qXiHLkam( zuXv5lb8P2H?HauUDv*W~o4Lo2%J9x2 zubq|;{U7YKV;1eyPQ7|i>~w^>6SZT1$f4uV@e=Pe@^Z|oi=#)a>&Ya@%?fH9_}Kh{ zfs)Jc?6FnVkUAviN8Pms!|R7RT_U%3*aLp@M(L8(0$HAZ|0)cZMuhUeAVQ^yTqo2} zC0v&XgFUtgAL+;wQ1{M^>vb!L;*9}U8q{fU3_Ggh=6L*fjPyvk+&FCdm^GCA>b($C zuO2iCH$o##qgVM|sI`R31{B_x1i8~urBnV)Lms$h7Q{t5yS+=Usi&3jTp`0%!2XEE zxq88xgtF9~tRSAH#BTFTEwzVIJV<@BR*^SI9f~8E;UU&+&dbGM;=v8V#*|rnafAWw z4GKL)q{-(Sc2DkDTYCV16SQN zG4hkFEsv2m5sEj@#Etwc-g?;Ekxf5cv`_oHC&J!B4BkA$%Hu5ka1nMcc5R>|K9@A7 z8Ja1qsoF91HqxD7=pH(z7O?&rjA83b$JNntJTbMv<2((DtHahFaQvEKYbR-xY!TIE z5_q4F_&K1C#V5`7dejb!m(rHC<$i~9Kdc$>{HsIE1q5uG2BX{!{zGnoKg}!mcZZUD zyOx_TPAF%wh<-~0xPzGn))j>7)gAFC>3}!gf)=e-@Bcf#7^T-&oYo^3uf43qj()~D z#uZaJz#(0!9oVKd7HF`V)W!}&p|v^C z2MN7SLu;+vwW5U@FOnAgn@|e?g$q&=L^GC5*XqjItk-H{naIjLSzV4mn7z){EGQ)} zCTU)pC(<6uvR2!oi3U_F0IER@o4J8xx5P9oT|h($$1>Dxo#v}ezWC!IE3(R<@K7n| zR7>UQM;ySyHxUY4#d%6G#Sf_GFjtUwo}W;vV_bq1X%-e+RFIQ3mB-l*CHaoueq^Xd zB7a#R_#8_wk-3m(O$&^AX&Z1w!M`b$8^EMNhc&|<-5)bkchCNKg%!*n(*hhyY5rWv356Eh-=gX(M; z1skEnKv_Vvi%Bc4BdKE&=uGcV5#RORRPpi@Z4#C_sc6 z8|awA*nJQIfB8;q-~isygQf_9p!ysFg)TD2W7XuaYV<-)K%E8oaZRKhT)UEI$w*G2AtvdtykwPqVz~q zr3AJyk^KW`}ih4a~K*F`v{~?9q?vU&lz)k5$$b z9W*TbE86Z1{4ncL_DL9P)ClHYjvq75_|=fwa-T|F`5C_J`jXZ2Kjjv%q}rH2eIvvu zccfn(a$}*@uSSU6E3pqlZNv|=F6M|tx$k7|3jD;(9rv+C@}24PM>|r7`MS)Hh!^Xi z%Wp!56rV;6#AH<6z&T1o4>BD#EjXTBfB0IgzXST5Y~g%?HFG*GFe_snJzjka=vF z>xPoG)X)PVZ}fA14a{3=V_vDV%tC_@8)u09w{YEcH)3jK5;bd+z(TU>8y2XjJNr65 zV-?*4%~-!TFshSfn<}+sAF2o64FgP%2=!cJ=8kf;nM_vCe&w};WGyjS7)kwVJ-Q}@ znY}lTs@{gJk24^wyNH|1U6h!a=m8326?Q6IyBdutDb|X}JbcQLY9OUTG=Sl|7q&yd zcc+klUogXK3BM;R!(_=$F8d2OO=IB3nv!BOtck0?@jBPOCf@t9<{N~s3XOMq{P@h` zI&#?hC4{hE%7=?Uyis2|4bqu@Tu-1U2sF<#g^}F($mJBK2*aVeom{b3#JD24HVyZN zN`5ocLM1tkd!k@vs>_KLAXXW$DE*b>f>y{_g;?wXR`ib7ru!-(O%-sGh!^_gW?VxK z<39KW1;wQ%C9OksVGi+-9$ps!Z;70U0uZUS*3%}`80b=u`eX4QP=VMJGjA{Ij!~*V zNnZ__?Rn1%3=l>4vMrT5n-^KdJ2goD2i%Jb-Woj5f^mJ5j-qT2a9O!120_ zOwo{TEyugZjzKlolgoKzk#czKVs;M^8&^U|#^~6Y$ViKvoOhzmI13+P7gl9Nb~zAd zyst%F%PR6ydBazWD(%8wEj#s!k6sPQv{_}C=5uOJs>hd5^%es`2Jno03fD4v*zafimpc^mry z@SnD+*oWty9I6_u*{xfNrd9SJM4N!a7t^1%8yyJEDI-o$c_-<(yO)9O?a6=g?cC^y>55)t721?FXXVI{nd}$Hb#I50PrD~ z`W@x=B=SeFfD>`hN~~x*#1(SjRx=*BwSrgxqAE8w3 zf|<1ONgP+NLb`zJuuIIJFSb94CEE6ruhOqw;A_o>TZ?L5_Au&$Z#Yaqtl z(-nrP5{t+Cc;|S?!m?Qb_3;k?>S=(Qxx=*sgiW%Tr-9mz?@@ij63qDn75(m$8s?ON zs+Kw5V+T{>ThP^*v-*>|%$f0*K;5XJv^itsGK*Y1=6t5NV@@f)8pSl{GoYGa&hudB zfO>DI$DGHy=4>9sn$6)1bXGup{@s6Bacn?EY3lB9&BGWQv=)FCjIgka_U}UeRnH^N zu(Q*}8*v)J0HmyFU;N4uZTQTe$2M8fBM4FAJJ;ZzCb+TBL9j;KSPfgaZKL4?_^s^DIU?u3J!c z8yl)>_bn=ia~!sVI^psKZkw*1Km59OzUN<+4h!2)HqPO?r$R`t|i9l+gc12-37znTKCwx7j8HIN_YeNRL0 zY(;tSYfYDnur@_GI@%&c%E2O-R85EF?T{vb1Fk0^WkmyguHm!qgQH7e90+Ki9iZ#G zM%R2B`_@`r@#k2!P4KZvB&t6A(BorAy3W)3ayU=$4vKjIBMbte+nL_<4McvqiRg?Y zu`fmQv7&o<#6}H~+b4*;l+2}>&Dv2{GkYK2ktnh_&BTwqdS3t{K}Ozc7^N7XrRa`B zUy-t+XY0{%d`In{+5D?`iJnI^+W({9QP+t1KL>Gog)A-&MHS&87aOqTn+HY|0|}J| zJ>pR3)`CioH8Dn2XMDi;&981YKyApED`meP0hQzHT;#&{EFP~shFVKeE=<2k3_=cs zEed@&IgHQg>cV^?0doiTec!eXkrPdN=H(_VI8;55c2L z7Eg!tuoJhM8GPDtd4|{#TkLAmJdHGGfF=zX_=*OEfzANsc)WNzLCz&x&oFsg7pFUx z;*lt3cYIs9b{gF^C5O-QTDLRncn*eZ^e|sCbn~m_tPn0*eT$VIHa>hA zjYEHsvZ6B+J70SI*VrFnyp*zC4mAVn)Auk%lO`D}ugl9$q~q7@MRMX(%1M-upW!FW z2qpIbK9#R74^5)y(&6$0Y9Igu>PoV7qd8Z9IiYP% zzeBs1XOc0jGNFbxLX?0S{BEMA_zv2yp2D(^(>)A)zpjca{E!vr%LXsl2=Cn9rR&s; z%z1B}r!H{jCB9C@$@;i?5@us4(8em_dnpf)Yh^hsz7a6~9~CxLlgtOnWUJ^$b~(oQ z7`RW%a9V%(3dxr0I^`mW9A9SL&P9$AUj(4><~*G>Hs>7(;AzgQIs#Byj}(Vd%;vo6 z9Yj}2DvSwM>?$$|sL5QhF7fsDl8lh#aWzOzj+2z)E{5b}kaV=r9A^@H|90^^wG6Wc zo2TJ{$ELO(vGWP_0ie8M|J}h6TZ-R6F~$CSyUPQX>Hs?YZXUaY8$p|=IWalUkpbm@ zw27DFV?*DUc#Kc%A`^tj(KgX=-PxE>TrQ6DiQ zEx3T3x`31j@k49fvOnQpRSzSveIEdTcBECzoyt};kI$QnGT<6`Mx{s+5cTpT;Pi9@ zL-xiSCENO|;1W=oTkGfs9>H>u(+%|HHLSIwgb2ISYT*@|$DYu`r#zOxXPofavZW3_ zgN09UEd*Cv5lh*xVp;>)J6pvK5RTypTh8$7)J|X1naCMWX072lnsM_Mx`Ag!QF32F zZhZWp9ezhfK=m^6F%(GZ0$Jx4r2`Q5ls|ZJ+zhudplYj2m=W8fN4KW*p<33th<%r~ zj-4Y^5)Aahj|m1ExRnAty}1qpwfTw_p$)VQ(`);FHk`t$c2@E2QvLaSuEqa4_A@0# z6__t!yhHrztn)3$Ts+j52$*?GIfyymD+E+m%7E{iTT1H&D$GcBbqtkg*|}Xq2xNGP-gMx)0EVnu+pG+jm<3w>Y8_z&y=vK8; z4{4@ux3O+xZ%f_A*OB7E-7e@1*(A6_)M_4cF}kH|@@XNwh)!4M==wG^%SrRz1e%`y z1{aaLq`ckGZD58*yNQ$WYXuu2!DfD5f`%y30nVz#1ByR26EF0duxpZ@UDRz?Yxasb za8{Q6J*lylis#A{t}t;5M`bQj2@dr&MRDdHzu*DyKQ<+LSC0_C%%&IUAjWkQb=38& ziVPscnz4P93V~`)idvAh++p*tOp2=T8#@O%xTR^YKd7ra;&B5{^x8&n1E14-;sW@5vM>F+60l86+3%ZV}XfZtFZ zXyIAZ-i3CB+he^1TgA`Ev&Oud>>cyn0)}Rhz z+=(Zg0mw*4LYhqu;2;4U%taSeUX|)0&#|v%OmckF#s{rb2zT5KLduF}@;TAsjrSy2 zd_KessQPb;k&>*#7%6;;EC1;?Lw@Jc<6`O91`@iOH5M-osFvgDcS|?I?*^kLo^3`Z z`ejvp&&K5Dp+;EP*6*o?VOERww;C-(&HWG#dIQ%-a8yCGb+Vi!(^VhlCCiXG3&QJXgy#XfB6DwdL<7&<8^mXw^N zt}GYDc2coY4*N^=JPfyQzJ*yKZs=gYpQso&pm-EJfRma6YAm=yv3|nyP>LO5Uk0fV{B%8}blGRNP=Q}(Y&`+24IE(KZ zICG0oZ?UTS0(0DengL=q?*>F=^(D09T(|#CyO!QgNj5?O|057514| zLrCEkU%opY{kDB~8MCu8(L}BJb7=oqnNZvUiq&iQn=?<7m$|@+MBXSnmm_B&_2=r3sB| zTGPIcE-#l!osX0iJ*RdP=+Esc=tdudLBKMXM^kwO&7q)ou8-ScR*eOvQ7jLkoa-T3 z@1b^*Lbs?!?;~*~$wm!Xey8anJ4Wp}of|UjwIr8lb5)s6|c7PD}D$I4Y9pl`F9%9z!IL z)4~R0x@Pak-XQ?vQ0#A!vZ7z`IZ=SM6$t`d${I$6_ovMsctbznek8xTo<>4RYd&0K zz+@qDp^R0L*I@#&t;lB;aSJwKb5YC+wb_C^morED*li+=<&@W-I7+d7MskJJR zC%VIqxRr80hDR$p;2)qS+HvYv33mJq!~-~IDZwUn*4a@Mh z^salhpa8ugEm%OlaxS5F%ZlXgeieMNW#vPRg0bUW8hY2ghXxOdwVxB{O!W$(n}n{> zU8`CrEvsI`T9v{V#i*1{R`I`jTE^!DsqfIY3^2avL&i}{?$YHA{@w}n;Euo}IYj9=R-tOg&J)kw|CZx#DtJe)zz z*G7q~d}M{Aa-8ve9?jtFs|u*!UU8hxc?HBndF?aTkx*6!U{k}{qFsCxcz^&$1HgG9 zl-R8dyVhx20+<9q`!=+hL?RE8hrnZPW_b_~)23QP#GNnuw7fe?t#`)78$+=ApG3p#kk_}bn`-ROL@Lt*3<6}CP zEtIv1h~R9K=!A0zB>R__jbt*3%<_xD>z+jF7f*YM!2Rjpns`yd5o{O?O+X9;xy(ll z?~v)eLS5X}Io2eg`oGL3j59*<*M)zd@KZFr>6|3%9La)?*_8mU6xKY?7;dx+BZy~m zwjEs%9N?dNV%dPY=4H0n>`H9exDqdXRdyq%PCh2Dh9K;YR+6P&0tK@HKbHs3B~J9f z-&k}f39KWux4V|y709hFkKqo_8rZ7wr}AdY!=# zYD7Y5MlD-5NXcA%u>?ddr_h^B;ikr0Jtj^CtX2Vf{u zt*AO!ZI2^qTwxoD;))V8?t%?cBCIw#H_6-A)MjJ1*4S9)Nftp5x)kv2q0o{P`qZWX zyJc4x!E?ZjYj`#{=Rqa}^_QYTtmt=|6z4?<_dQhGlIo6?wbZxe5E1S@DZUD{tmtK~ zTv*QXP-sUAch^DT1T6z%dwzvuMLTN>rn=e_?Sk59u)ANnTk+KnggQ<`>A=7l7Eq8B z;|5&ngvnZxe7^{t(;|1`I$bRy%P`&bNZXABzk9KkzKLwR6Y32O#dn{wUR>vbZcW3V z%5EF8>&Or*+8uq95fHO~j}W~`{$fpjx}lH-XV#}J;G-m~_;(;!(S5EOSfcSz=t~M6 z>Y#uYLjFz2|0I_`)($<`yvEi3s#J`Sz@IaBU^k9T&$~HvEjz0K6fj+qT$%C=v9LdU z0XiKxn_1Qks7|HQ#n9kb74z`oz4rD^wRz!f7rt~$&ubRCN%*LxFQ7wD3raIS7x0XL zqr~GtOu<5YPbdQU;UEFzqxlXY`Bp}#d~!y%6V`cQDqow+k0vd>&RCKeMK{Y*?2Gi)(xq6;OtV|Vr zLpn@+_E!}wgN*8Itc2j}FEKyg7~Aq(r7i)WkwNb-kAG+wx5>riouu_$K$Dm+H#wcU zAQkoG#u<^eWVnnBpMDJz;JZHjUm2^Afy_C_#0UY;s2`TIi>jw$`1bvOzvNR6&Sk+5H_#jpX0kX_#Y?J!Pf&m!$g{835f_Fq-G3GRL`3>v zJS@GDbUTx-nJl>P7Q)(H6G8ucE)MGbQl)zxRJUu;Oi1eaZiAmKkiXIECh~t2kkzHM zuD0G)uR@^_1f-Q0;bR7BEALNuf|6`k_0X6`8k1ZaVu0?Xajj;?U}Py(ud~-7?U4?% zo?d1@BJQloY$lmiu1FMk?Yg)h>1xK-dBEwg8vB^5Tu)8%c`w)-?b~jq^D!oy-C6)#eEc^A4a38i-W11+@bKB=@Vy`3i5nk+L5`}w}09DUW z*@S>!pma3pwGHo4vbO?Uht#goq@a{^YDB)`%aMa{2%cJhx{kanV5WHF-SZidntAZ! zGIE%r12v@glMBTBBSmGsDPS8Qnh^KS$3Eu*>m96 zo|lEb?eH8Nlf%&(g#mRtWDBT+Pm45j*u1SGpYG}Xs2t-=J19$z$YS0kJOF`1<1``N zYz^qg1nuB}a<@Mn7?k<7$A+O?HYp*uc;072P)q0%PIt35Ba4;5bN=+VF`tm?=BMQw zyDU%EYMtfRUn#U!ku@}MY`7yD?pr{Fh>qVY#R(!sLnB2%6}*A^F`mtN%^WzlZ9_qE z$G8!`q70{iA?(6>w&t%POo{JZtAg2gu7C+V3T~ z^9{Mg#$fumeS{by5RPxQw`N}s{|)sf&CRea|JHk|wwE_LDEthi-$`lTlgx4`b+L-L zsgMG~c|A)kLG&o0F`&zCZvtElm&ZJbsj#=HdW+MEF2Ei*HF}RK}pQuHb{Bg z%-J*M!SD$@8>#;l{S&0_|WT%Xc}?wR0?1HxYnM+$3>k^(j~qkTrCRA$S0l2ZggYK zUQCzJZW>^-=oj+I1qC%2$gN2ag8^2BgYN@J-N7zlq8BwS*py;S7crdJ!kiv)!ixx) z>ZII^I3o?^<)nPHbT;-v>N~b>eOnO8a`kl%iw>wckBPpE_tmLy?(n*WXhnMK9~1kT z-a)cfAd4D5Nx2s5#(uU}By@o^0Yl(pZFa(`!ar_3Pczqxb}4Wjwu@nav&ZiT$Akqm z4ua-e&J5j4$(>2vv}jWqhJv3dlFO1B>7rgJszgy09PhBZhH_8h#RV9O*b|h~pLPX8 z_3>@AdYGoTFIapBC59H4Nw%YY9x*cR+)22GGm!ruz{i}~1I)-nR{36DZ_ zPD}%8BVO!-MlZcoCgwO~hz6dVpH+q;>i*~9&Nn&QVf6s5sE(kH7`T3_GWZ2VP*)I% z=Vu6;!($;?5}M z9@2}KLT&b*^C)i9a8GOu(Ld`K8B zye0QOp_HMLN$F_1vcSPE{!j|*AS-}Od~vPb`58P#AoZd&X~$59tq=G~W$A+VJoncA*?G< z1iVrc8B8KP&7WRSmUQfYxsKrW0WK<^_F}~z6JJ(o$Dy8+4y=U0v$NN;S6PXhe`5@k zb!G&aKxWS|BuRgAFQ21BS11;cInPcTd*&I;*cI>olF!!;^Ka z&N|AIC8tLfR^c<(GIJtixS56;VX~Y9s-08c`H_eVZ1CH7vJC!dhs1B|0X9-*c(RO? zLp)iA%PF2L!=;_cic7h9LwrsvAMmpat3bVa;-w*vqFvOQ0`$U*6qy24m?=QvLyV-V z9+073rU2pIp`%C+0KU~>_v=X$#UDJHRlOMqsM~l=fe5!!PWHr=NR zj%3M^sI_JOogGSDk;x4mJYvhR6;NBj4T~BgxgN>5yX7cX`29Fs)qMJC$~g-;LF8{J z^2fLrNGpvKC9>y?E?LZ|h%XT)swou*b;tL~9_hc)Ts^xe1cy^iY?V7ME+a0vcIHx#^+hd&ZdP-bp^afvhHC(P zm*~-UhQLizmk_RDD6BG#S413cG?%>ZwL-nUr6r`+$Y;LdoFE7`py zTS(~<+xNuxb(pNC%8!ladQ`gl>^^Zm!)QAheRiLhQ6Fpe=^za4m%+z96IvX@Lmif( z>qriF3vnwr(x_!oEYZM&hC^}Z#e`@acV4;PXG#J~e9ONbHlTPXP`p~K!}uq+7=U-Z79v*)S*69rtkf1w@h8W1ZsIIT?XhZGmrm+l`wt@tt<1CL%(R@u)r6! z9LjkT%wylCIiKEOmm{Y_>o5cd)IIltaVH0mSZTon%w=_SmI$ga4`gxJ_liQe?g_szom$p`cjhuM_P>i8JcL%yuZ;iSDLc3c4kQEEWF-}MF6|Zg}|!QQ@VZE7{hYe zvEW`Y@Zo4gemJG=LG9cgf~|gJ4Chz-7Xu!>ZVR*x9zh~&1syS!@eWm;XuDeo8DDhh zWEC~005CX4t2w6s|4i4NhfnJ-(2hz(W4@tD}r4visNRINj4boh4Rw&e%d?KDZ{cBdnq#WJ1Im4)UgSQ3{3;zh@%;xR&^1PLC+D_M{n1xSj_xAmP=}fWRME+Rk;Z-!O+0)dY||u! zO|9Hk^4;Bu{paQlo({|Vn&D_JdEvGf)DJnDVJ<+5zuk?zQpQVaJzqvJGP*TY9MOP{ zCD=OvbDWj)=UUs3Mzaq^Z7iTnd_9A2s=|3Lvk9bfJE^#@h{KamPUBXG8><4&OwpT4 zJ8{M|EEBQ^lC|5lI2ecGIa^oS0s%{kV^jqaeBtyK>PH>-I1US|Sj8f`P|aOPUH=jb zRN4#J_T?amS&+<%PRDPkJN1$}`f}2ktVHljF`(8RX>31^ z1KyJhFyLJe0`(%V~9QdtI~Cm|Z*joqJ*pa*yx zMxd#$GW2=FN}PU2m;Q6WcE3tKj$=C}g@#KZzTzicUTMsABW>DrsEBt z56An;I7T3nrinfsPVOiSS-w*04dJau1Em?32qTO zRmJoi=2Z0!6XGUmhV7x;jp9 zjFc7KfM5C0ZwNL9VQ9?z#^W@7U=@$k9EnGq+Ena1M!07PSA-_i|2rLY{p(A!Q2zk` zU+SM9iLmn@5+306RNU^ZZRym3r`|gcV7(ul2QC9bV-5$oKT{+_(9Yu>>_Nq-^1o5# zPMzf*sZN67a`Y{@`i9)lnd<-A`}X*#s%!rP7!gD!z7St!R5U>$h5+Fq0wI}@NJz#c zyhMaaGLRXPOq|R>P!xs4f*8^Is9L>Z)z(_A+WM@ug5LhX`Y6?F#YYSEQFn|F)V5MV zbHCrU_j$}D!1Z_kxc85XA9Locz4qE`ueJ8tYd_C$SB4ubX}YDH#od9aB6J)2JGxoS z=h(*!CxInX4bM!7>3CoigM#YDTcMfdcF{@CEnFK8mU}Q}VVQe^X5%cEjZL=+8x&u! zhBG7SsnUiI{jdI_$+l}3{A;ki&!YjUGd-ZqdjuOM8XBH0DBvEMJ!*sCdWVTy zx8S>$ORJ@ZcfII+){#Q$o&7vG**1O9Hb8gt-TCX13840;JouvR-@ zzn*EX^UK;h%7s=SO=I6IR|w~fxfoB7>B!P z#}aKm&}?n44{Ylx_c!4IDEE^on+?ENyJvBn_dx}iF zA!p$DRJ*U)(9zxuwjg`YB+*5G7a?rJzBak~Cj*_m zZ(}z`8REN#@HU!L@Mdaptb8|f+gY&kE}VA{Y#T*;cUyHO>jX6&QKAbAs%aXMoJh?C zdn8XW$tN(mrbjX}1l5YG_U9HjvB*k+`IJEQ2t5|_OQ5n*pX;gz+X@rVID_l62s+eHFqm@4%a}cdG;wIVa53H4rgVBiL zTjiv2K<<~}ggDi&IW?i*TjU%r&UXz*K)#Ke@z>)N?q8ek6m9_o=l|Dyw`QHlimvi% zM}(C+kA243;Eg+4ZD;RQEp9V1dS>w45AvYg?Lm7D>rM}P7EN$9~Tu;xB=_CDt-%NaDrE405aoVa2S6_gy{mO09!&iNRo1nLDfv2(LHtEyl zHtDU5kuAAR`YhZYbOJCiD{0B?L1(Pmy81%^;Cn5(J!qudCaw3og1t+~-uqWVvREAC zOtri38QY<;S^T>(BE|4pYnu`D1F4J%tGvd@W<*#WSbq%}SCqeG&9 z$=1!RJaz;mxFvzVdBvt1A`FP0t{%A#lJ6fKuI|H+h0kTmx~R;|@l&?kd~h-JL3)Tk zveheX`X!$!mFRMV>Y5A;CL4O!X?poVwGWWacTpkIJKak!?xlC9(DNC3Tj#8+tpv^oD!sbql?i zp?8YSUzwqIoTi8R4kEoTpg-1kqnBQ`m)=7{ZeFV5i)wOAvdIV1hzpEp5a7aREc42@nvw_9f5~aQ^gr|w9f+$58__?%*c}A%Iui2tmCF2Ak zqAfU0cPtZmcjL>ePj-=xaF8YviJSj`gllHGb;!4oH@>*Y?_O+E97N>jHS$@$YaSBh zpQRu_VUYW&otuHo$yZRuRX8ia9{Lf7&+8qkj{~u*8CWA%{nU$bu|w)cV(?Q31?ZeS zG+qp8&ibi1G5D#2>G;%v2cynl^ie@#46Of@x|ne(B)YYI8dw5FC0Q1Hw81+EO6a9UxOIC<%UL#Tq_q(gnv?~IuMAEh%uHAE0|Oat zAf6qS?>;M0R&oeSmW4FQ!_Agkb&{{`H?$7ix@MYS0vEB0)o>uj_Qt1XruQXJZ3;*@3QF|FPs?*jS< znlf_O7qpatzEtB{E`>=oe%_AqhoXGLd{8YmOvvoaFjIb=r*2*r{_uj$!qH^mdXzVh z@{=V!0mV~UcmZ9NuyDA;LN;08G&e=?Jke8H?IRlEYx^)w!?=L{J8AfvGf)nVS!4+& zxz53U+bH>w{wc9M5_XA~v6l*#f#a^lUXA0jLf59$#RtiM7W2cpG}+{!`Yqr^^`%h^ ztbdNb|4B(~z*G?>5$Pd`xwa&JnI?(vYU^K~jxv`?&5am5>q@g(4d=GoKi>pYd>ha; z^HWkPot1+95V67iE;W)-%G%9m2Gxh(N2Pe)iIqA}S3yT3Z?Dw49%d*8)mbLl?bn|$ zIFmutpt*4YYhWTHHH33eFuTDrX51E3=Os8B*g4shd{qx|{sirXIb_!8R{bJ#PIMDk z;Wrtu2DM8qWb`2orm_vy`4A%=R;RlM(epJOUz=wj4u+@srOVpSM&f96c8P4~7wQ^m{nZ(CoEW_%X&20EdW3_j8_BKa)1{UeG_qpzKyE5%-QJE7= zWp3_K8NY_ub3I}M2dzw_ROVsF-#VKpidmo97H@sti~s-EXU;IYKAU&j^?7U!>ch*^ zshpbS0K=8oAt64eZ6LV5L+aw`VwxY-jlb<~4C+L%(lQRkIf&kL6J%X}828rYIMk&J zS?!i`C{~D=wHHZLG57qG+;3j2b4&MgP#F(5#T*RL*CwZ+4`4B;$-XUkrD;LLue5v| z3JbcU>fS8ros%JX?sM)fo0$ob)YMVXy~rkGNUwOgu`R{T+GKSbxQLQE`(nu1yZ>CE z#{vf4Yg|mquVdObg|a}O1(cMJBIWCavZw_O?1&^kM1KH= zYe@ETA&{%O;rhC;KfpGLBe0N`o;#hdIubb75cn+#NW}2YC*V{fhCi+bEJ6eSfNd$I zuYAowaJ$X^oy2J-TI@}=eXzQR4LF>OhYRf=!}RnE=$TP-3?g{pyl>+}_$%@INKWhj z1w$8)jWWQXG#V5)96i%O_7`gN6cgm7y?%~CmdJRwVH!DY1F#2sVAR(xXQu3&e>cbn z3bpS%Ai-n_#qfZ^IcS(&=@PRI%*)+>J0gCW&3u0maoe|hbsYB+m$;;7Tzo0;4-gTb zZ)eGLvW#LDvG08!2^mDhpRYozTO(6ze)Sr=zZ9G3h-pZ#5%IKV?Qpc6&8TmqHyjnv zdks>K9T86geF;Z19G-5y1m*W-FJNo7+%O>#@e!u{{YAvjV0Roi#;nRZvalNExe>8| z7N@fC1lp{y@UKo`4P%QTWMQ>2=nyKADuN0P@wL54%k_+TzH3C>bt1~ynBw44BI5JD zL0z0s@KsEQFcx}C^LZv_@h*q@Dqa892gg^8KZEPXz1}JLe_-+->EwUuGF$!MD5*PW zJ_%UoTJXfSaH6iM4i_IVl6S+!eUv0*?S_l%3=S3w4;(IjNG81D;)zjqz^?B*9Pgbk z(+qg3<(jAP%eQe4_%hCs?EP$6x@tZE1ad)MkITSu4`@b?Yi9he&^|Fimm*Rcv=2>5 z?TAPK;L+xHjp|Q60n)7Ymh0J#_8(uPkZ6l~dIgZq_Nt7h8R+{oGY<$}Lft^T{?WLq zSqXjo4z>t6O!r;$2!8oC{v3a!rP4`I4x69{SS@NGXIl~RI9;B-YdomFs>kdvkSA!R z`Pw*j6)o3-ar~>jdmQIqfG@{fy#bV&(|d|dYiI;ar(T2-RM#Vy7J&|GL8U#||M11k4s7+C)d5uOGDA_EDZoKK%$z8pcKk(M*R_*N`P$29 zh7QgL#5tNc=6Jw{D>A_#c08<;ul>js4A%u!5m17v75fgO7m-D961Wa-Gxc-t^N;o2ac?pk@gVk*Unq4p>86#s)0uK-{dI2R{hGxNlVYb~9(q@wpt=*+A~^Nx(`ha` zr*&CJft&qq{b!7uW`mEeqY@nv@sl~xIflOgEGZKWFQ{@*pu;vS$?*jI*k0$FItpW6r4o(JL-vE$1oQK&O&XgXKi zhr!Jd?yK&~DQrEyh6)JHU`%auUy1{4>eB1*%D@SSQbU@+9+<$5 zctf?%lBzg6Do|POg)qHjCN8b*J`EGT*ZtD&3|6pKm5aTD1p$o#NW1~9z9Zn|oa5wd zWzL}~IR*5uMaYSc$K>9P+(YehhdQ}eGWT0Rbq6T|dYZZE+1BGKFi+0EJYsWv33F~r z$tj>KnbR$I7wnYh@Rj>9RN5hj)O!HlMX=tCO}9~Kz=G|7&Gs6gBg;ZHYvNl4zT4A3 zr(8B-JDA-eI|_F|*6gfycdf%z&ej_Wl<-y^NpPXn91V z0=RP*%+p8j4o0U%7psr%#abnI0`7rq7Y~O{fAg>{p_?h8%P%sr<*_0Zg-Yz!7cAY% z(t%40sn|8Cn5z>&PG=bs=K}Q+`0wF!)#Mai(lHs zOJL-oE6g1Yhtt9!`T#2NB-({JvA{O;Km+=uTEG!wYzRDwcHoBR*$bt8J&C2vOlh?b zcW#$K`%v`}Er8w5_Zc$upgIRs4LQ%Pgub?)foo#3S`g+Zh~-r5AzPSFveu&)dJR=T zM*&203)b_HwfZ9~=&s4LV%6zHPe>*D&V@aQJ_8VmLL8)u(~2s34>%!V$0`%ibi!MH zVRQQwxm}w=SU`1#u;KP;b~ULIQjI={Q{2Dg$U%;-9FG>j(_%`h*T4qn9~Rhp`DU=u z%LJ%_n*N%F_pa&ZFkRfoF z$C=Ji;-Gr>0=HZ}u+l@Ap?Ih+>~IXKXMw`9EL~Qj=ZJ1Ag*|WqSlKYG9_{pDOirhd z(q16W-!2dwGnNw2YZ@fkJeklA+2{~XYzRCojmsRG)}5}ejbUcA4tuD;8gMeT#$IPB zSCAwv(m45_KVVyhBsU`2b+!U32dKL_TYbGrtDddROED*n;`~&KC-$VcZ@y5Z-0syx zoiH&rpYjCX{uI{#MAm;N*@mhkk-Hb1H;8kW;P}-i-!gt%_?*6r6&)NMhwk7qmfmX| z?4Ex|-94W3Xc+tMVEq+DU8Ek|gB+<@t(N#3FjYRZb%mI+2d5hrSu#0oYK@jC;nF8i}QhC=>C53HQu>3-_gdGMB79( zXPA`ZYrl%M8HXGc_l>kePgFi^p0vk@(JVXz-@LPdK7f)Ttt~XuqLS{4{~gCMYfNnyf;^5au^R_XR5#5zE|4TP8t|I z!zkpCtLa_IbTik3$OQuh)Xy$deZG&n2l6I*ulv}i4*3eM3|ICzI2nK2E0+wS8AUN! z%B}K<3-80O?K$HAH%YVd+~ljTS#ivc8u&3x6&fH>(;kk(?w-!?fgM)^C*hcvE&U<7 zB95`&g|bNKO+4)#cpMr@Kc2Wjs>z{-W5iCB=9HMl5+9i3mS~$ZziZbvAAUgH8x~Ky z8`am%ibW2G$iTab;xeX8bu7$)&!8|gR5ikMDRIuP!+}VkwF|$Mw#Tzs=y(?DaU?bO z*^NVzha=f_Bm&A1Hm9+j4COkW4m2d`quHYPX7Orj#vI{z2RK#(z&$PZEgB$N!}l=4 zApDDeO6Qbu|6QgrPd(Ly@~%22lFyAGoic6_=#_wS+>(uP%WBMSu!t492>5U;gQYTg zE-3}POv1oYRD(Gz?O(KNd~KihliT?n2l~ zL(o_Fni|a|**q6%2T*pI;8Jt%1M5ky;-dp9ZwSe9M2o++{+nu7ftK4ca zi*0DnkKQR-*QG3GDfcmtmaPQ3uOamHB;RD0vOcgG{B1^(ec*!;f~=KkFxU=};9SiF z2l6gvB4#q%SfdRV%q3IXvt&L2V7fWzte{elrlva#3C1BdLn0^veNd_OSa3n<#OFL^ zPIb$yA!pAJ&r?;!;7`a%^8H9Q-O}dHOt$m%`pTu~6ai`xCdFl@Fq3{DMYUn}S(i%xH zs0m^ygWdVt)D7p0ufX+nsvmwyU%W%%a}&%-hhU};Y%lOK+=9#EC8YRmFqOp-4vUi9 zg=CjS0lfqemi*J`Jf249uRpe{Dw*!?NvBQd9Hx%fLNyI}6`6|YBGgor6p9DLI`)&J`k=u1tPJ)JYoEopuuFNI>n$urtAbmoM5M8T}HKYz9Ej zLj5$Td)s%*`5dacX=1SDlW0}PgD4=3|y z#H=8Nb}ATm0>iZ>0bKzQ8i>E(g0l6QD1c>6{1;#y8HvyIcyCuwo$?okUO4{?ebhe& z8&-Sp3pnRsMqi9s%Z!t3aQG=Oz;MdUH1$eQJ-Tn-}S2dd!f|`~!w_ivZWFC_(iTRu*(|c#o61zopjjial3+-DO^n z*ROqH=OR1(nuFJ%+F2$6GO*|C2PE6M@4E*RAbf|7CJL3JCF;U1*W zH*}$i@41VM*I_{GPF*x=0ll8P0@0hCPj(kyM-{k7PP9+$`Dhl71V~%@>$5u!|66mHh=K#;}fNhRprZGzj6 zNdE%Tr%|rmW6uHw)feXhIh2CjMdVQ$xfzEhZp5tGtPMwbcBrY}Fqhmw`Z3x>|R- zuw~J%^zBZmlM|P{1Z(DP?b|VeX>Ub^g6ee?h0UWN$qQ6FGWM+*pjG)mlC{)l|D39P zN$xhD2l{5E4OPdzu#Yu^7C!bdYaSGLY>7D;>U{4bA7B7kpjaT6;Pnf4O^kS(OZ7ul zCNuYs9;bHBr^DK#7UStku@A=EoyY9A=vU|VTJ+NZyEG0ZjqRnPiDqrv0(u4@MjzV| zFv#WCYBtmeF6RNBD%`v20D2Ry|3xia$>Yj5366v6qY@bd8iP85Y?KNcb_X-g*S>}w zdk@iAM1y5#!$JRk_-Xn$R2(@Q+8qqyFglJR~%|z4amFQmX?X$X0LN#oz z2SiU%SJF`WM^96&_`&{girNm#(+gG?m1=Ku>kN68I6mTRs_f<&v>eZZl|a`4+Pxj9 zrn!$M>N2AC+D1m8I=!@!qX6!HjEqJvQyF}b6|iw+O;(zohkEGtzAff+x0()FW8vkO zGO~3RUf^jRp3fsA?-mQsvhwAQK}gt#+x{^1`0#%U75@-^%SdjLDez@})}g_zqh(X4jXB#3^FP1CfAMPzoI zhuO7zPEKO0T&6lgDvWy}fZz3s9W9b6&giMHKnH_aE>w8$`0%yyNE7HI$mQg5pJao6 zk&E=oueZHwl1BlCB7T7`dBQG?UAX0WvN-S_UNtAfCDq!^kcS zE{3YBE<~s5a|)KSUcJsP%UvK($T@YijAwdF#Lcl8FChVi$i?*;?#1ZrRE4kZz9pSpm;717wCn$C_l!0 zoe#O3c&foEBE#Ixq;qBp9S`CX7x9Ng?302BHU!!=U6e&8_Y`=UyoGsQMrw+J1^NV` z2;{+J*AbAuUSV2uCM6FCqgMnN%4NK9i3AB+GMh;8QlTglEVhoo%3Vyl5J}NYnygL-{CwH)UTjo!!aL|2 zq5}X~XhVKaNIyWTY{-*@Akfd4VMBgG2$mxW+*T zy=boyEk-nbi!Sdke#=4Kk|&hW&DYo~F@MrhYw1zoK_N;V7(hbsT%N z4FG7yP6X8`qor0oVt~i%gam6hoLEeSN0Yy}Z z;Zbof89SMAhR(Rj$tci?I%9_v6I6GfgT07ce=e~h*8>8szB0=d(d#w;n|`aGcMuNm z&F-`1DsMfq_FIon$BCL>}jyrq1uK^sDQa2Q?-rP=_>v18U1|jA9mF;)h)R7sl=$rtCBtB=#z6$ zl`A)2j{;LKy}6Qd&#($8L!eA-HHpeRWjmc@{SCCJ2l9! zb{PhenYyO8oksIC8s0Kd^trah)8P6Z0rFWw9w8uZ#>%{C(dC2cUxFQ|JCPYqt0Uvh zt89ndH_=}$V%$yeNDN}dz%@baroBrV!>Qf^2C;zuHwjh5I{Z@;1!29W2OQI|cav?&sW8Gf#&|RNJ`*w9j`*nR7J*4ZsXhzr0=%HP2 zNBeiZ5k0KywdjDZKST$1y%;^bYpe0*{cUfKDO0$R&xdKp(?|XJayTi8U?E zo}#$ufGm~om!&m&V@Enm-1oL0?Oe^(-Erj=rR@RQASlKMovx{Yxg8fu0EZm2PkWH=b)5a5t9qYA`Xyi zZs(u&ddsRYxiUKWEvx-;IKLC?3?2?^O|E{OKRrOM1)b59Tq}}?i8KzueR+2CNE6_~ z&haT(;>lwqOFx}a{$_M>hZh@k4@rhP_h53x*4ElRA-QaF4;2hU>lSTy9{DZ8_z|v* zTp#w!vwGTm6pfaiWks*Xb-~Tj47Y(9HpA`a>H14`lCgcvtVlAxt%hx&H!%nJ6hF1! zR?y}O*JbjkUYPvdD$OLX_~-PEj9PI-OQhsx{q}fWKh)i6Kv$cr7(>zP_rW!uI-B0{*^YbirwT*mJs=fvqaHaMgYP8Kc9EM2>IFfPg5 zfRxTkkeC&DdmVny>hqQm+4{U6Z(Pu?QhP7i+l^KF5!mJX(II8)F`b2x@0m!A9-@B7 zexW1dYh0KF;eqPcqJ0CXVE(?Uov+{wRk@s_6 zk#Kwmyz5=0`l%Q2qFTAB)2$pfx*di?C}t-&i@+787Ca9-%k37Xpddwpp#b}5HZZ0V z!8mysTWfS*Mb(?W+-R2!0!d%N1Str256$EM2}Ek!ZWKZcElYS z?+e<|Y7}18(Hi!iz=o;g3G1eZ=*ZAo2&xRix-{%eQD2$*T)!@r*AePnysB*)wn|`A z)hmQOs$oAh*?vvfCJozZU_T-38vFs@PhiL|66}8(4Pum9FSza7|6rRQ?eGon%TDi$ zW1;H2JGD6@qiZ^M`nBmC3hURV(?^}yDyEYdq`x1!>o^_0w{Ld{tN7iZ1&>SrwSB9% zJO{_L9OI&Dxye=IvMmwIZcBX=x`yrBpS20W2i$WVB`z?R+rJ*u)6g5)6v4`%`j=4$ zmFIBlP*dMzX>K{2^!iX4=9jE*-v$K4@vkt~z9GQaARy4f70lX2@Z7-_NH?!TxhwxL z>8A`XFP!iqBTDlk^IViDFJ?-`o^Xtcq{#IsQqsnWp<(W>U0jUzJ);=2V%AO4Fl*yY zJ5r}rfhL@1YT7>}z{~g`i^h_c?@b;2ZF>S@W{n_Mj4$ZV)n#9@g|#!um39lRZA*76 z-AOI&c`O!MgffMmt;}(8tv0Vg3WBcI9L?U7$JwlV(k3AdqczQiF`I!L3HD}ZZay;d zm2Eg`?;Tz{OJVJ{i?y9$Fq^o=;RVs5X8KXEFI&nfG}+ zgKL9F$#ItU&5#)M6onw!I6vlg#*U0uToQu0q@XI$@AJ-J@&NS!_x){J9z=?dhb_U)2H|-eYA4 zb7Qtp{S_TA00E36q4WRy_dg~9dRqS5-&3br78ZDV{b%R16OS}MaF$m7(dY1A`n!f& zmYr@t_Xkf;KNy~kf3T-b$A0b)-%humHXerI@-O|FXW;vL+V}>|c?@=b=^yFxO-uf7 zzuNV%pXmf`c$rB^e^wZH`qRd<^V@Xo_c;czzo(67=SzRu_Gsf31WT>T>M|?T(h`m* zBC#g_l2D`}84p|KrDguQa6G&O|2Nf!t(s7szb>*o(h`eHT5~*B8?FPUzc$p+U?o;I zhy6>Fp?IA?9FGGh(o`32^~aJ4e{6|A9%@<|255PxAyVfrET{@tp?EyB(vNZ@OPdGP`tsW^?Xx@1FmlHY2GH1SbVQB`ftt}ZRBvI;B8$^wPer4{8> zR#kOnY59yQYgFFovE#>17?Y2Mz)=(P^2UrApO-r(f5N!2e7 zTv`^WvZ@2~s*5V;SOs&+sw)Ek6jYX0msnMW1?ARRqs~10@-uQqp0g@@!KD|Sd)nkF zlSVAOjB!|H!F+3aU`A=VHGRG%btc_vtEhC2Ra9XG${+>&DJ`}F*HR%0OX7Wf301KtVMg z)w3(ht?H5h{#01im9qm@_55JKnq3aLSaS+0t+^$roK;p@Rb6ETDl020t1Q32J_1!_ zTa&C2ertIs9tqVng#B4omcJ>yJRJ8YTf%j~S`msjMVgiZv6&jguaLhb5$6x6I2nds z0a+4h4cGZa(N?&rt|8pg;ztGj4Y61=h=`r|L1P5|Z;WUQwGc9vE`mOtFu97c(C-Vz*`wncwas4?uXi-k3j#!#ZR z9`b-JnP6p|(>s;43?5omR*ol27A(g5Ix=gdpEN1CN#}Y}YznBzl322-&T33HBqGfX zE77)>pt02XT`8gNwaIu(WO>*hX=I(PEHA075gxiNE1MFbR-?j56Gak-df`B zU|vd^U8u*R#vu$$t?8S&Z03)Zy_4-h`9v~LsuT6bh)%mz+V$;iPUOo>ei9& z9Ts{R@UU(OOs_zPg6_hr8~8N46&hv1SvAyYoF?Nqbq1pyOSGfASxIO>vw$PgNTTW# ze9doN1RX5fruKv4=iC}LCR-Bz`Vd-u16+KAKi5!mFjCvAr)t@{#g2f9pquejKdZ=V zGFj5)c#=~z;zj_LQ=)_vj2qC0!0(H>>w4K;68&_YKh^}paX@x>Au>W{FQ@E&!DotZ zBt>?jGXj+!BBopE(W?B}xg$~~(GaQ$H}rI<8Z12yCGB@ijum1wV+jV?)4hoB>)>0V z+FEv$Y@l#D@y2jnB$Nm{92%Eo6n}9N5f!Y)>&HEm*%kI=f;@yAg6uRrZP(46?(6c$ zjT5P~+gG>;vVYt5<(@{v;?ZnaiKn#SZoan@XnCSogE z#^hN!;nuK*FHJ`Dk2(xLa`1?Cl&VIWY*|I4iMz+8+@g7d9{=@^An zQIM5Z8DjjhDvS(@iZC?55CG$Y>7@{984!>-17nq07)u~n!8~E%OpF17Gp*vX3g8u& zRa@eeib|`36&QgGH@p@UfxFTR0#+4&ap+K5WI<6@aCY?s{sA9F0Srv$1i)IcHCONe zhm!DjbUubWl|_6hs4l4jKjj#c%&O1_yXdxbJWNV>4<1O1deFT9a z0b=sA3evBWk*Ik>Gqv(Af5DCzfYq`R?YnU~-)K=ueUnmi>a%x&ytelAc9hS$~qHzTia`A68|KQ(P{j(VV zJg<^u-ksn4VWqr%hZiYS2n0qKPcO&~(?vC~x%i3Av-k7V_7)vH277CypPJ zmpeXpd|rNW{&@TyonMrfn?DB60RAhs#*f8oUj8^B<&7VgAHds0{vA7ZZ1Ff`%`Za6 zu}BZ(7UdS?p@OOZteI$uvjXL_1J${s(Yy;Qii@orxWoi(o5Ng;KFf-&vmy5Uv1d2b zjgkg6s&zvCsQj^Lb2)jE=A>v)T?0lFO;%k)%gRP-tgb=B=S|4B3T72S``VFka>KY3 zzxih&N>7Aa{7d5DFnV>XBqs-dMxfOeAP^3egQ0V+)2zwX@k~jkTyLyuw-(k0o?AqBUZmg10b1;lya04$w4V z{9s3BEz-Vx5k?ajx8b#wz`96FGaMUB6Z-H|7}v%@w9X`hIH^S{MGr@TVzO zTMsB2gf*%;Qj3;{DFMrG6)cM*s;t0}8V{Rob7HL50(7y+`)E8~%+^_Wwr9pTT* z9X(-GUT$9QNPj_70$FB4PO;_I?3U0{%-c8wCO3vKrqpBCDNZ-zUl40%$A<10Vq_24 zve439kpEn}i^v}fGEFTp%ovzX1CSZBOFeHzWo6pCBPGxZm6g%e{gc_}n-och7%?o?K>~)3waXB4`e*6Zk!{2` z(l6o}>33>D$Ez*EKRF8;si|EN4`q=qOjYKK;z>-rVE&`FK3uzuely#QUs^^=Y>0!VU*hh}^qk9`EL9-MJ`}4y#qOo{RW27k-m%6YL##4KPoot6+s!Fmm20EY& zFp#7Ki~zKvMle2}X+YAkYg(~`(W>~b(Sq-?F0}k`dXNUXww7=$A5x%Yw+M-P(&uvV zeuWL|*8f(Ur&%4^ZQgwbZ}-$C^6y*cY3EOU4xgsq)1SMirowkUuitkS>ZkqJ#@qd@ z4f)^pob2~GEM0Vp&-xACC*x`VD?im|m3iK6IG+s$eu;UmGtb-1^C#x{OY?lrJYO}> z_sw&+dG0gMfhd#zhMMPa^PFs+l88V5)8$`~#!vdYWz7s!mIunln9S&-`m zh>!GJbv+00Oq&t5lS;y&Wk`}e<00{;mV;L>9N diff --git a/programs/develop/oberon07/Compiler.kex b/programs/develop/oberon07/Compiler.kex index 55b5adbcf08dbf49bd4f0a2f2816e9357163283a..fa02e0eccc492c9afddc63043132cde637246a24 100644 GIT binary patch literal 270605 zcmdqKdwf*Y)i*u~2?-%^0tAW3B?t(J+$t!Dk)VW&iVg~jMHFv1j(5$d)xdy5lsFS( zt5(~3t+v{FZB zWv{*V+H0?UJ@adhSyZ!d;-tJ#C^Q29^%_1a@ ztVpQ1AQU}4au-t6)V)F>_s&A3uI+);JeBSn!jHE*n(yt3cJoxUz}p!u^matMd+$e! zymz9--kZ@L-sWhD_e!*E}Mdbo46JVJDPtfc@2WT=@@oM!cU|cR33(28KzvP*>PGiBB;y;m83fDNl=ZKxm=LP3rtReJ{tvV}Sp z1w(+1WFZo_6y>Awgg)+A)>zZ=*HEajCXK%vYT9WQjrHx{WipXFsm*9lb$xM&hS}J- z8>v$CdOkrh$00ekC z27jB$EL{)pgJQ#H%vZyipuJrtR+fpC5|9tTOaVyCFsa>;+FMe^)2jPX1Cg>(EDc0S zLSIiJMcco&IK$W`Q5in&y}-?Zht*jmpI=Nz!Zx&l`0$qEis|5_kynMPVZ2TIp@M+c zmM(-2nk%4ebO@`z$%B<#QWU++eHcd2Sg;mtQ@k8n=1<_OS_E-X$Lenl;uUT^5lerr z{a0~vep-BCfx8}go5r6k95jjii}N-ndsX6b+Qzywq?dUuoykY?j9D?}^(IrQcC&nLi7!5k*F2E=gI6^?*fQNW(fqwx?{)w+O*bY83% zOk3T7cTjo#AZsF>A46PFs-{8zNbE{|fKW?}AkBcf%u_!Hy5Ee@fYhpNLNudp`pO66 z?V9Wx{8TZz<>(Cc>uh4Qm--0g(GvA8xv;s4>7xvzv_2Up7#CN<->`ZVn5N@HueQxs z06KG!?X7-CILbx5=pkw~ene=9uWrMO#w%1S@a%gSKcYZqTAEx`JZF6xl* zpg)?SdpNp+yv@!!Dj5ROPg(e0gzszNVbufdGtl*e6j1aRd6;g|QAq%#vr2|oGeaWJ zGQF3&RMOe2>2Br>ynC~J%>3BY$V2hWOb zKs4P$eI zRl0}@pFY1~BkEcR>ZC}1V9QKs2lE;b8p@NzlSR=5?jdAdaD#Z}tcQg6p0;ttA=Y}@ z4~KabMHjlI7F%0j7@lz2W`TSmj(hdu21Il1-ZSt{K1zq6oanypqxj~gGr$nyC_E+7 zL*qxFMb)>~9V(4~=t}s_;-PRafY!IJz#HOa>1n`x%*LNL<7L$w$f-Et4*h!D8>*qE zln&BhmHM?xjBkcs-pzSnqwxzER+UcL3hStd=YPGmVLdRu{-%CwZI4MW*T1)-+uXdD zmKbWb)8E3vI37Y@Se9hNLhZmOmnC~hQX*7fs*}lt(|e)msDiM%Txijc`u!`bVs7=S zsiE3#AE&Fw)>t_q5+QS|tCuGLEcp1VYC^XtBgqLT9-oXAGxS(mHfhtOty28@_f`(L zuJ?5VX3sfl+Lqex4I9U7_PW<^ihVk%b;+rxP%Pi5e~5mc<;mX5lLKbYp3{lPCtZ2i zp5NFkYz_kv^gR`732XyC8r?}1t0gwyH%ypl1u86WqZw1dN2clG(Sd3=rU_00Ta_hPWUJ~ppwW1q&^DNd2Nf$xE=uogRR&GR*V@a2S)A)=+o#P;ma^! zR2xu%=OK`5;6+5w`-dlW>y$ zFd0xdL%m3H#6$pGV(gDOGHO>5UZ5Tj9OMTpDZ~43tds~6(uj~vq)=B9xsh2P%&Z01 z%qZN<)F~o)j>9gA2xK1-2^v@sR-=U0#1l|!I`4UjI(|tOUm$p0ETyNMGS}1+GDCRi z$~zye(n*~LRHtbP{x;T!5HUtRLH`=Y1kuYNcjqIW4fM@;g#rItz-8(|g2xNEo0Hl{ zxG>l;XoV%@QmX2SRwQTzbx$}=SHl|^lsbk>#bLSARG;NCSI~N?e%GFciFKmHNX)^f6gFlU#}pz;vMh z3vY>l!L$*LMzUls`~BbKB0&eV9wM@zoj-(EcmJCqrpT`D;IkR@t8>33ATXwmhJN$j zCz)6|d(;l-1q`7M1a%l&hSflzw@@z}sqz<&p(OG(>w78K`fiXT1kTLXnQ^BM$Cz?D z+#!a;NNA|povhi75)Q&oa(?@?jkSHntL?^cuW|lvs=(Wh2roH*_q2_=pS2w-;zP{- zI*+`RT$Ik+lI$;4B{O+x??$*x_h+bTXuE~A-5^t=*I*W*cQmgN9yrtg6(D)N;pWY_?)fZs%UaYIXBaos?}TMy z%n!R%c+xW+jrF?%&%6C+c+bYhcDy#^HP)x`+focS2W`M37VBBv(@<}X^*aCyV{VN< z(b?*5sf(MPdKo4gyNDy1;bCnyUc13D*KW!6cJIY?Hw_MEK+u zL1tt&!O3n2(Nv_lYMwF)^9UfFi|{C=_@w|k72!{W)B(aGL+u&@+@L z(v|VPe1Kam0bX)`1zP2J4ca$`B=`d+?W2)mJuwp75b6%4dkD_qMF2EYGA-;zSRxgM zC@6+HLw+$en{JsUogrs+&p{$`E6miSz0U!f+cH;RW(Hcvp9PrEb?Oe zq9uwv$wj;UMY$+w+^b-Fjip-}^4#fzke z=66qHz<+L+49;Z+19b+8HaLz<&2G0)vO!q?1(-QayYM%gT{no{O&zbZOQgHU_RN@~ zx^0MfA-T`^K@qONNga%G$E&kU3(=Yi)%WzwoXIcTvo_8r&+|1;RQ_ok<{uZI6J(PI zHcwhMKO~!sJ4fcq=Ji8a>I&ldh}O?xK0N?u+|)x#y1RuHFL9H$c{cyxz%<#52#CrW z*$-*gg2}yfGffPg*XnOVSO&p(a}}B2kIC%Df{kd}4E#7S#N^&`)}Np+D)ucv#<4#m zdg+$ryaL3FGq^?~Vg3BwGRwU?k>0m<1k4ICBlZw5?9t=vHO#6Cv}SzW!HK{dv}|^q zd>wK2CJx8Rf!@wK5!hBwu~K%yh=5+%mC4LSGtzL&Muw(a5wgfUcOpFjEopv-_pXn{ z`O1>Wt<3EKK{L782p`OiC%&CH*9KVW86)GaT8g1waZrQRDIZ9KhB+>jCp77f#12R6 zv@MO5A4tiRb6ZOgPUmgx3XzZ-t1X>ycN2Fvh=Y)Znq8ezgzqlm1|eyY0rL@Qp{Ap; zGAQD9hBVad+!O9j;&z5K)a=+3?hfK+A**ZJHy4R>8uw@Xp3};f(=rzZ3g>cU;@eVG z#U`q`5^?c4TN&$M%&=$|KtnC4kRdZ{Zc%&NxB2y3otvIde4K~hoB5mgHs9iH#{h`y zgFQI4(Z1UK6EbZ3CO>cEIjyS}lEwFtH24C$mv(!6BT{nzR%x}d2P%z2wF(icardWj7Sc71NVX!5(!H%c5kQIYk$gpu| z6@$E*-EBLDVrtJL*iNhs3XvKD8t9 z4Gn=oo;v`+(m9*N5Xc%+^A_@-e~GKw04CH1s>{%Eh1mTN&@OZWc~R5(!6G_VcLi#U zKJ|2QD8+^Ezy>#jn3x?Wb5^S9U7c6q4j@Q|G&hdw+zW*5T1^FU3RMuL2T_jdjPefa zkz$ie2~kFOMxibEC_RZ%*cs(fcpe|6lqerF7A*+Ka#u+Jr592D5=3Fq2TEaO-5W6l zbs8)>YO5!8qK$yYksjhS5iO|sa&kTkoV#dVAV*1_=v-i6STMqD0hb$ftM5*eRMNA@@%Ge49mQm`$w>iY$bM~`s+V_^sI%xnZ%{=!a1u{=z;f=v_Qv+v;%@^h<{6U-U|@K zm{~4zoA;T|P34h-u?zwSOimn|1<71jSWEi@%X>=@1Uk17{b@nk#^_J=9#rp9*iR zJnX>&36I8e%+D`4yku$HN8R2?kIX<+yVP(O#eN&nsqe4Z#^6*+>o>(qBAn)NZv`0j zx$9#X=4Q^9tU{`wafv?u^*g}EPJ?7$M0pSwWL$o8PXigIy42%BchZ=)#Rx^s%9kv< z+3gV6<)gD?cT$|}fq1cgE4VN;clVLZk5d;|EWl>z1Y#&;kkH$_pjvy5kL4sJ0s>`g-@~9w^^Vmaj++{(mW7C1%H_+8Dh8A$mcy%zIU0cm`vO%3x)K zuvW+9b!HS%k*OJ!nP2I(Eq#7acAu_k>JRTQF_~HXxm?Ns7$?0t}bw$xi_ZU`k zERA8a-3`HsRztWHFe_LGq|i%SMbY8zSU@_hYccFWW$9J!8G3;8)Gp{H+*}G1&~v~` zF-GtPdswuke|#z};Ql`NFo4}>@S3$z_!{mf;!-H0IztV@1}>;vnPMbR4f7+~d$=$JT;q=6O5 z^`t|S7E^tc?ZvFe=p4&so5(TlS7;+L!h?cQ=g>1+prajAQ8euSgDqd(h<2AvdktxR z{^fIJ&q&yPkerMFGQKI!%rE!u_v3ZHC%Z=^gF<9~hLhryuDl?K;yC#_yrT_QpnYIt z0+1wq#s0R|%aVOX_+{=i5gz-eu;IHLiy}op&xFt@eX1B{*fEU=%gA^KN;0;rbm4Ti z`#B0I)*a+j?7iw`>8V25rbGXdNS{{MLqA-(l9NqHnQ2pgy3&A7jTOmeCNJOL_^weW zTGVMPv#SHf8Fs-K+KK(_01b4s$1G5lMuy4&cGeL?XDk9Vf!)7&yfQx2JgQ3DE6HU4 z$C&DaQ(6m8)_H;Az4z^aAFiy9OME(@lmY!ss6_WydfHTRDTAZ_zfp(AA+l-e?!ymi z{rO(wGpI&11$jhKt~3fkr6n33SES3D)>Fo zi-_Lltn0BjZ(~ADgcW1Hs1&g<+N4Mm;yhm?G%kME-)N9^L~7@Il!^}AIxWZSPC=8F z$dYZ_S;NI`EwGutc$xxSBU8U3?`N=HB7T7M&ilEr-$rY*U5d)(ZM`9ay9LAQF(Kuo zWV`pWMDpAOc785VD~a~9`6bfhV@FH$j<}!L2m5rLGFwl&54f8^XEr;Snb}nzvcJ$2 zO3TSu%{H*wg(+%LNDwv00JOLWYHmTzVanI4j}Nld-nWc$+r8zO2v#&jJ0DZvaan2_6Y03qv;z-J#qi2ALMZgb|A6ZG3V*WIJ?DlNct-> z*E(}CHgj<TvtqifU+!=!i1zcIlbS^nz$8@GDHlY`y?c!j55}|(L+fV0LAF?9Y^+h? zD0a0LtEX84d6R9=M3p|kN5zJeEcTtyuE9PY%zeg;C=j5RM*6eV`RX8c2H?(4!7z*r zAgG(#he>)2Xu1Gyd)Aw|(Qmka!7N&2AaQ%B*>J-@QhCW5hPBwYs&!H(+N$)!+6o-A z^TXOo32Sv%SP-rBp5Z>UK^epsh;Y~W5iSY`H7}GOgze)cY|mgu2oszVc`@xI6e7`D zj7>Z_$qd^w7Zs=uOmx^00XNRFeTF)(mYdEOyD6rOz=%fOhv@)I6zj_w&`2e?Bi?U+ z6R}PuhYI1y!PV0orOUu% zk(&e$S-8 z1KB|DoZ)iTFa$9#DEyV~R`g@ZRTL9e&|4s3br5)p9)$>aE8RZ=&yM=`MQusajmZJFOk>SIA2Y#k*LN#=1ezk%?Sqba$X z!`!gKN_*WshB@JHxugII-Jsr4A#)U8BD7oG#_G-EA}cI@4&BTmu#jb#UE<|yoeeeR z5QQ#z40`0@RzBG#@d$VX3|V^NJWPLx83dR3(OY5f8MaSDKj=7KVBvlV;QtHgiaV1wNZL-R*@mXB~Il=!uW%?srhy z>b6lJ&KY!Q)-~??04G;b7)w&)Ze&^m#lXHfE|+TL+3q6%h~ODN%Q^0^kq9v?`5Zl` z*g%$8jKyD^l9=PJ0ao5dMB7=s(~x8(^Kj&=SY3`3o7>UuOuPju;#Yp#DT*E={tQ5t z3x=alAtlniVy9aA1#TYb3(J9!mG(H7TiXgNkeI9cJESe zuvDz}lsNT`V)R-wC%89*8sZQWbvD}yaiUvCwz)zqcF*3k5GT3E1cdPRvRsz92W8WJ z%`bH;nW}{gc`GdTsc!Keu$Q@CpyfiuG7+(MI1AF2?v7o@wf!yW>F%pQ67^u*?k`&zSzAQU~O4!MmGl3b+Nl#V6-qEJ-E^mUEaw!fNrQJL(|R02%s4RDM})%A((p-VcH~N zU_M=fuqwd(##IuLv@u9a2HTfOABOZm6EmsbVZ>@%S$4ugj_NFe7G?FSB*IA|cQa6v ztLVlMgbm38lLS5nU?E{)#lzMD4QHl|X7n@_i#JHnP0F9yU~nbiBLVIdTrI=)c7*J= zyo|VGxDKw$P)jQIh6Gn75!oroGYfuv#qRYh@c|eIWBZ(RuRKR=Yey&FLt(p9Sb8Aa z$~8>7+<#zXYbp<@P`8H3^v7$2Y18llGSTq_0mjxX#eK}_HUfebtGV4z*eb$;6{}&g z{%|H?zNKh@tS}r!fc8Va2oI3kPYBo#WfF(4DWs>~n}9)G3i}X={)4e=VPzMX?56yP zu+g~;Wi#bQ0_a&KCo^2AS82SzF z51zS^hN5x*O!<}q*EhMo+#q%-QuzBQtl7g3!*p29gFge69s;SE3OzpU3O)V+1Y?oW z?D2c5HLv~X9-otDnJEX*gn$2Oz(yTri}`73 z5e?!t-TNHja#)wF#>_aU(Ym0|`-_SPGa$Vrofe6uOgDe_lj|`*GKXsP@maN8v1O=5$ zmbgbt8e(%Du`F??lY!oj49#}PIO$|}q@-egk%7Vq$eG&!xwH{1vKay(uXAKyb+Q__ zi}-m(UG7Xr{x+|u`#KU5ZQu&|ZC>ZPEs}~2(ah@~$e4M3OgRJUh3NqLia?81isIqW zwy)l++)KfQYPuL8j6ud&71hbUYC=9BOH=MT_XsNs`Az^WMEA~<7h(Q=>?F;?^c($z zf2ra)4nr`1_x06mSYM&{W8Hr0XHgOnz;*ycyJWl+Q0CGdjJ2YC>oIFRsH7o0DDxV~ zG=^;Y#25v=r_0$ZE0b&`k4v@%punI5v}T9-MNHnT$H`E|Tsh~9lO8xe2}IgsNre0P z+!;b&s;&aQ){Ft{2Y@d&2LcrP3~6O6_sH%}vg2haRP+G>b^>@C0I7GYUb170>Rd(? zPg<0Jq8K=OJbbe*yXin>yt5iyt$Ev?^>NA(5rDqwhKt{f?G53RgwLfo7*t?HFS?M# z=}63M7EE-s;-y~4f-w?wuO`z)*nrJ_w(<;Dc_JQ-pWGX}iCahoKRII%{NyD1$x?Ol zrvC>&DN=ZSxp#9x{8+DyyJP3ZXM0858`>-WDdE-J+~*y{h;B!`3@Oz7G%T$$c_`13 z?iHts5#MouE9X-QDv18XyC&GOBs1XGat&_*N@R$#{)uPv^8udc{zQY}aJJhkI?RNW zY~tj?x9s3A!yr1iHe{9}Br9(`N0q6UP!sXx&D^Dsnb^!744H{Ek3S#_JDu*b$7Pvc zjSq@s@T|SSH9?dHLFrz%B7PM{dKQJXWVv|f@UY*~_!7POA+&7=;C4$9d|T? zL+HwG&W)|G6%MHdW{|t0#IgnRb0~_Q!(VVECi)4IGUL0(-=yn=7sOQc8CKJ8B^ z-F|T_LFtUQeU_W&O|3pE9qk7Ap-$Oo=Yg%_{MUJ+L{ArTHJ~WE!mS6jnMFN7A1lB} zra~G=ZSzD_f?gIv)8M)jCzOsS1s9z#yhJZ4X*`dz*xa+y4qK8flF)ek>uuo$=*J7% zq^pYKbb3d2mnt^urnw{uLD}89%Rpf>hr0%sa?_b(#e^8xvZG!=R%oPIGOE{i54z+m zqFJUAw|E!4mnq~NG|Q}Gyc7V*KUYzZ16%dlnP{xpEJ)mq6!$pGEs>tPmXd#%kFalx9faUfMvc%FBDwq>{tl&=oLJc7w zBz8B6uj#~WKAwhKt9UpFXGwjlK+`DqAo~*;lq?NeS9rjy zm`w-%o^an{5hri^Y?7qRqnq3$?Y^YI?20uIbYj? zdlkkprjhK6?JOMc(UnH`&*7~%CCj*gyFy@pCq>8RTJuh^W|us9ay!?WCAkdA+M2`I zShhI8^C-;|OTjyhXDA?_YPLx35*N?p)IWv9+#>J{hue(7iz&jXAL=69fb=~J_$4W> zAw|HMl|&@@LL>(Sgo0r)-vs2mN4!w&s2|YI?yy>|F*=uI8VZst`L~qAU%*VHYhvA` zsJhMQ3i_Tn?_%6qOEMlTRDRW2n?r2|3pvs4OS#`Xndyy^=pTy*AAo? z^tU_#M7P)#B*QOu-7Cj{0e*1U3UMxaaI0l3vzt3a^!5aAs$l5h5hzv!D3HafueX81 z><2LvdY7b3#6ouTCprh&XNlb>@X#hcW=vvZ8x}0Pbx=g)4N=Ij(lS_$5Fr!qBH$@j zK#jjLfKLIth=&_VbZC!`ko=+XQrR$P?ft(OW6VZ`4*!?MkZq|K(cHN$nW1XtZ>9^y z9Caop8$6|=f*~Ly6djVS!rB$fED|FmT#4;%xQi$+KG>ESJHSwex@>$21Jw$V?FqGq z0_#hlNsY@(DSTl}-r69* z*a{aE##wW#CDCGFug&%NQ(Q);O`MzvZmzyF1(+V*OvIEvhJ_| zVwWN%S)^yN?9U?oew`G_nl^HQN8>)7c65R!TW-9Trhpp__E5#739M^j-h}n}9i~Ik zdfvdEU$I`M=_YC|@W=v(osH!g00yDM({XlM_(G+A!BT`*;K z3FJ7q!_z!abFsm6e9TJ&n6lB^8w9h6#v>+Ma`ethq$k#mi!bD$unhNiAWX!S5I81= zAwKlG5`+C>bps5J+0QTaT<<{aNUs|aM->BcXf9$^5V0ik7wUVdUibBzGUnwl3jqa} zyXAm0#yXZe@5->GOP;(q;w<<@J6v(!7p!qkil?%iruF!ni~Vj8`(eS}-%0&OuzB__ z7n_T_KJQh6J;6!E*rs}lY$2B?OB3l?PKpt@(}a^+;8CiFq&R0N8`3{SqI)qGGO=S| z$>UPH;&9z@LOkC|amS3)#4>gv-a+EYns^9^8#coZH2G)9GLb&oNu5QBj`C&ag7+pw z2R`D9f;iJjaZc80;utpv`GO!aTU;W2tdlyOTyYA;Xq#N$4oFxV5A3X+V|Ju7SU4G z56VHi&-x8^2C|k<>&03VhjtkL@Z_$|ak-1&DWHZVa{U*H z+6d*jPSZuwB6Y|=or7#tH;BrT^U8W?skuuMQvl=Yei}#MkOhCeWmpzrF2nz6aqKJ1 zA_Tx=I0hJ)%YIUp+T4vY7LtilI5hH04J9!IpqTJ|Wiq><;|<{AEv#mJDFK$~?+x(C z(O;HNGUWB(oY1`Z96c3O5Z~?1=2Xu_Je~B!cnG@?7;xPsCbYz1`~m@a~+1Xp%CjQziv<*yG2-J zoNfBZJYhIPx8fbbS(34FhB9I$=>nU=tw+Sc=L zw$+U&;GgcxSD!heAoJz&)klxOYT35)Migx8;Q1~*a-oS$t7!P91QTo|{@xba9 zv*y0XI%Q5#@xs=gXwyapakK??YUcaZofc;$Y4)|4?I_caf$9jb@v0K(y1MZJ65gv| zNCNxMgCr%9^C;oTve4>FAx_Nf`-WBP_<}PowcO>D47DtSdiHorK_ylD!|;IMh)dRR z4qF(yYlUHVC&k%sr-?I39%&boQ9=30F%Z2hL%!WQYv%r#d&;RLF=GCo8k zVk1EBg|SYKL{RokRQ6x7cKXB0#yC_rd#m+wZv|>K^%nAVnl|IFzV($|^(lzHtq3kd zK3db(IKG>J9kg65QilSgvrV{+%%B-3b+z#1KJF~VwqTIPdpKCK`{KuDF`f)y_@m}5 zn4uE-KPXTRnFYr!re=5{9~TA2=tJOH(xu?sMcPlL9&tNI)+(|TWBRsWkTTF6fI zbOrn9bK)5JpwUC6vE$G(_|z>nx0#1IGZVRvQL3K9;Wik@Xd-eG8Do~N{=?Rgna6+$ zAPkUdh8{w&iicpyY7i5#Sh7iY*J#&9VFRuun9G5UxYjPv~EBkj{=ksg^+W|n;y5RGFG98ami>W|sJ zj)C66c*E$B>cK74TXNl+v5)?kVu9uYmzmALCISNexYG{6(cW>X0rHQJHZxhcI^IO1 zWhk&4!HS4~@|_#ZU&F|KA_zd3NKcDn9kB!FZdzoWgxAR%;&Kv?B{451w}dk-;cQMS zgK%b|wWJGe1!+IWDuqw`G6Y|*X2H+8Gx}m7@n9|__EP=OyZ-1c;}vL0Cq)h;haT$6 z&EOd;Q?KARGKXpTYPqD9t7fLnV_G+L9G{Qob5AuJ&(yzMk}{2e6A9?0%D1ro#F!#y zGO1Jz1eg|a9?=Z{?vhrj7BkK8|AHYXuIj|hRo%#V@5n_YAFZAT3jK9nT^SN@Wnv%o z5EF}{d%Jssx3QO&a%fiWK3Ykxe;{U0bsM;%VXM#Z8+n{*1!}FNm8o}`W+bYWv~u-V zrWuKr;Tes`b&ACYI;pdJ(_5Z~zl}AIMw-Db9POvBzZZ3KJQCS2yp3Bi0ee|sz11az z9V{?hF*Hi(hZ*{9f>WlBAx=NRDX4ooK8^IQ!1}765cV}b5+NPdr+9FhKEhw(d}ru; z6Xy-V>2CAySxVW;)fe{w_N2gYQ|Ns{f489@DmZ28HR9YTIK@uta_B3OE{*?;SxgX= zKI#FYTqG#HoYXR5^Ham7T5$GJ*AnMw!Rc?sSR$~#>RiGm3T!VYRVnlX4gL9oQ?BL^ zr&MqTST(E`*hn>&u-&CpLxq#tfd^chfxndT_kz<)6%pqZ!P(p9|Cqq`Q{Ha@!`@)f z4|Gy@3H`4P{We3tfjB9_*~dxkMi=KaVe72q@jrs&sC$SL5u8CzYO(M+&hYuS;0#o8 z;>;49!B!5Z7ptR>I)kv$0vqC_DulkTp|2F2L23qZ3Iu1U)x)8NemG$Y@izJcC-n{< zoTjb#OFhgNoL(w(H*j7MoMATqpBmUFgxxQ&eVx>;LjMaxf41Q4qy9piHG(r-n}fE6 zs|}Ak2|rWdBb?Mi;c<-N(Ihzi)m6l)7Mzh*hI<9JmpYZO5dz!KNtFwIZ$tl-;Ph3~ zi4zi>QC0`92&|79O4!a4>R>dwZ#+0nui-Csuw8H})OU9Qr&Vyq*!=%3uxaW;!tNCq zW|eLd`s)q-_};qNJWZTcf-}}hdFbz*rvIRiVjhPJ&R}&5aZVPT1Dw>+!e_SObE@DB zP?r*Cs^E;Xa$F{`KI%lm1_^AulPVSZ?uPza!6{P*5+{v;9OoH~Yq&*V{nY@%-WS+J zC-n**oTk6xFJ*jCaQ0GP-U*y$!I@<9e_mj{)!T&KCa|A4sg%%PW9T;v&Or4Tajp=Y z1B15k4+FoE@Wle3?4;%jkHZa*0*AWnt1cwYWWkwYW!Ot#z0~o9RS4`LCsi!;`G$VD z;OwO)5T{*S@WECG(*(A+>POf+0-NfjHsZl)!X&Nez}CU%cL3*c!I@_BKTha-t2YR{ zRbYoWskK6XwV}82KSG>Z!I|!)_+hWCUsxu5_ESmXgazkNCsi$c4l#VL5u7pVY~mas zI8|1TM+7!V9Yt7~zz%a#+_C92eOsi<@v`6yQKN{n3yF#Jj5^y*2+UDE3F9qTxK+eS zwc^2PddkqJ1*ez#^mgDpC^$21{)J_%qh9J|!fp`Q;ZACm&|hij`wGqgbsurg6PzQ0 zwlGHEz16jZA1!dqwDJ>9PSZh#hqbvgh%;JnYOD+g3;j4Xhp=l8{byCj={W?Q`jo=JapWFtV`vqs7&HpY#zk#rn zz>aiMbwYocp?^ql2B>?86A_%FoYaSyr*`<+Es^mB!zWIhS%QOE-^s#fyy0Vg#}eXH z3eJ2h#}=XQt!5BbAh2VcR67wTz1vW@cCoCke6VMk!!%ovbjGku+4yG)L^F9(2 z=@YFE77A>b`tH|&wF+#plX_I>|7hrAhW>5h+$K0D+5GDT)>}PI*eZej)Ja_=^ie~9 zqu}&Ww-5*0)R6y@&VJ!u!KqM}5@)L5ob04V3!i-rpJxPTusW7F<$|-+%CSvgjyjOA zG{ypn^eIkC;lXM87=LLCN^trqhdA68ok*W*_3)j*_Elg03b1B@Ept-$3;k~m{ouZ= z@80Tl;@l)Sr`i0+3ar0+jIb*NcDj>_2>t1XzFKgGs3zhp6r3}Hws4BT`>6{FpDge* zozw{7F~sn=Sa1fYqlm-7Rw8|tm0_*G2B`^zwPO^SNH2F%JMrK&eSp8z!M%b5|3{q7 zf^)Xjf$gI{zZI~@1r~8q_X_Ysu&UsF1knq{d@EI*Q!_^VQ;ni;DPc zg&-u6zQ9RwGS_M1^bPfJl+f>`x)Eoi;9O|+aGJozs84SJ>_LHDgq1L%=eH9`f1Tir zQtOGcR&Xx1`Tt2^2dMi9J5OMjIH{9`{scq6U2uM)62zG+IF|-(!GV2;qeIjggpU?@ zE#hC{(bw=8CpZJu4B~L3NFp7xGRzTJnHo-*LQtMaUxxS>4~TzFjDDiv?5{Gv1kMYB zb2)TyF3Y!CUMsz39z4jxQ>A166vezHff5Fgrb+an1E@VYaXWopBcbn0xA>f6?Nqr@SOnqsTlf$_?jOX&Yyxvg#gV5)MWKtKDEdX2O9jz#3)lE zGJg4dj=CJ3XM!TLNYP!kqc444%7yt=@06-dG>5=^VB|<5_EUfO9tN=iz^a$<2PV-c zvXqeis)>+?2zgm(vj!EpgcyU>`NT*P;}z0A8y^{IB4nssD(ux(y~<>)&qf|*@?J8v z>MgB$jmaNl!s7)d4^TXK;mxjkoyk+M>$zYrB>b`u*Afno6h!y+?&1LtjXT`C5&HtDQ%qH!smY3>Bi$=ei)A4H?vF@hssk@RuKxcvf@!hL@?#H3dL^jvnE zlE4qtM|6!WQ{>PNXT_N6a!U)>G-BL2Dmi_ z74yJDkPme)B!lc3;zM0d%bVhAhE*>2Nm_MPxmCi-6u~m8cK6#;@=Vu}WK##gru)b_ z<5U!#@BR-=2Xk^F(lPEk^2Qo0iXQ8}6nIjzzThqJ6zth z(97Nafj3OD@hw}8wb(Z13w^Hp&khPLg7`w8=e{ke{OSPaeYIvTaGz(QHE3a?&GAC_ zen4pVegQ9bd6iGrZgl}Kad~J*ato9xdy?uZcM0IS`4mO#zXOk4{u8FZ zVY-WSd$$NO#$_oTHd8qqyNPg`eVX5@>Dq|Qjg@y0P4>5yL>?eten!k@#16z=WikSL zY6s^{P?0MK>4KV%obn1%-Nv|c>n)R?6iD;xg$ql0WU`l9-<0Jq7j0F7Hn){k+)NZ)YBK=ciz>>C{Q*iApWZ=ew2$a5IIsj-OHpv;2k+1^WwrAy%BW5}^3#9fw4MslXnXj%1)3V*uX%UoW~P*?z< zxe+=GyWCwuSn-}!}N5{No=00*L_2Qt**M8r3whC014FS_X@Db$=dSuq__wa=Guu)eO5{279t#*MZhwtzLz4b`adG2GcA6U;GkyI ze;$@}ex?a;2MAW}FnQB{8*%HmPzPl>2S38nTMrn7ptxwSWq30+gBF$HiP19k7P3HZ zx4I28GpJ-TTg69lFZWQ;-_uF2V$FaD`;!2|y+o+@5rh%z9z72(`mwoToD}?!0rwSW zT^qNIxQBy<(N;hiHM-Cxktc{V5IE)z9h`W=_!FbT-KY|+lD!4Dvr0Zi>8O$upc<`` zEgHR4qmRnfV6#CVWzi*vJnv{j=l zz`x@A{@k&%kG%hz?*qB9q^G>I>=;e;hB>+4ff>XJG|imgjny_4frnI^XT_$*=LtMIe`NdX=uz3*p8w47NS0V zZ`Y0s?oj6I*D;M|vwsYyD$r>1V(YYRGYW(Ga{L8o06_}RTta-< zX`*yUu0S#hRF2fx9K2KWl;QLzSYbK>me28Y(*-g1h=4Qz`xK4CFJx`2yIQhY>7*_Y z2_jm8y(z(R0b#*+hR8i%gAi!q4p;$U4Rk6VoTi^>&_2F^<72}h;CS<%HTdOhx)Ax1 z$KlGm3ll8FekuI_sY^MC{5?D;(pbA&E}(5l1HZupapN22=A6{C0(ugE0UAQk69U2t z^K9heG~ELq2+&Y~wA%KM@f#>sZDSz=WnnkuUMZwY>Z+yMD#`6^NxG`8uhVph&SV&q z!;*}teQsWJnhw^WeF>T(peiRd6P)AcA+O;~<~5v&G#2Lh=?tfd7m)%qf*_vHOQf;> z$c>MvfBXe#BwwVWt3;1u&3jglL+J7#``MU8bU7+Wq_GIeVG6$Eg}-33pCL-5HIoC( zdzQ&I`bjX^7figmMEa1r^W*1&a#SbEaa}0yG?WT+g8b_27<}n^5-3Ll)59tFrFFyO zG=MRD-xm|6PHG-11H1g7Yozbb^peO$D7_o~lGe-7`sy|vEBT%SI-unqgd=xoUbrZZ z9)=H$nGtwOQ1&UA^Z^sOItSOw6(fwl>pjky8TW(lo}z~rWI1)P^9!692}e%mXs7Br z6JQGDEkGDSbHqqDk7+IrT1z5dFp~!X#f3C749dBkXFx(?1`M$^HtpG6DcBrVNk(rr zn2ZE?zMqkIvrw5^9pE#~NCjGgl2A%$Mh}YRJ2<03m~7ysMflQ|Kc*K@FM#A)BFq&e zzBv;IGbFh?lI36^7l$1CGH>42WN)l1iIg$@TTI6n?q)_thmyJzsmTVSYc)yYhe(tmO>?yl z2lWpRQI?g6s%Z<5k|I2+JN91)hdY>BhgeV6;gsS21|Ac_+`Vg%dCjH8#|Dh zRg&u}8VhVgPR54SO9+Mn@*e8c-y|(alT9I+`x$CbEYBE(r1GGSZUEXKB=I#Qnsy@} zfe}A&5SiRdCd@ih?A>h*gdL%KT^3@~r!oB!ri*GyUP(@Y<}8UnBd0FS`H);EQAP1)2v;etaT1a|TDVHv6(=Ey!?RpzP0vVC zvo0uxBc$0@b2zNTD+{KeGqDHIvg2?@IPO!sBv{J1EHkVs@01qlFt1YBp+xT9Ct!); zH~z}>$p(6FylLY*p4`p@H-yP-AnfeeiE)NOV=N@bk%GaS?*xPWoyi67q^Qv*gc&s%dd$x z&xCKpP$;|Gnyc#WJ)UnLwOy&7!|=ay^eZ=ca#D+Yi<;MWef2R zt2*10%!m!<*Sd92o>PApAqMwO2%sLy50v}$e@HC{H+DEP{Ri3bW51pgyf56iKW(EmChhN#3QYUeoILh`Fx{kRc!CekOHUKXn3)XWcBn#MD zNAcM4C@beB;Q8m82?{YSJ(I}5IxyW)2D1sg=Fy5QTRE^?jqUf|=$v|0@1fFI2_pc@ zmV>hic+=X#X+506G%q}!4y)zP7(1QCXKUxaf{UCr&C+q`GGE6sU*bxcO$)+@e|ZLpv-0X5E(wEvJ5G=glH`sM{w`DtsbbixJ8SH zFew|q>4OR*r0qaX|DeJ;vW|eYgdL2`wl>!6jP$`Iei+NgUQ9w|WP*xEyXhaFE-V`7 z@073Q4M2$W3|WjM3rt7ZYn@DTZ^KzmF+7_)OTGAV)Uut4E{U{~&1*P}lxQuGwR+qe zt+B97Hu;d3OSL^f05B#xHwQQej4c{ZP?DIPqE%;WPR>RCP? z!{_PhPkdg;=R?)+_`I0URq9uKK84SRsYX7Z&gU6&6HMeRK3A(4)6e7cOmz;QFXZ## zYAK&D;qwt{0iQ49^DI@v=M{XeQ4HZCtNA=zjpOqgKF?9Z_p{b&t#FvQBd6Q_RmI2iinrSvNu znJFA}sWl&Jmc?i)st7bKOy-^A=nx{CnQxiOzw$>fSfSfQ9E@843ZnhJm*G8@)FPwJ zaF@fhLy?O#0Nu-bh&N3fDqySy<>8}pTr-n4%qEKko>}lI>Ot(&2YHX?xp>1Z&iDc? zOjG@QyYGg0)C(OCHznZfg_>&k-Ns{Z0E_dZhH43@psp73%9A0JS@O=hg+#h2jxj(7 zeO=@Rc7*3badZP82kIb*-_6ILD)`g)fKP4%1v(f|ef@ihy!XPpU$sEXOrdack4Lf> zAIIP_3O(*!S&GWqjt0n&CH>QvWIdy z_-AzrEX$uK^(Zk&3C@ogAE#XK_NC@WvH7(Wg7fW)uI{^UE zgucY~2zOs5G?d~j*|d%Lg4_}2R(bTG=APRcHv_HWI!;(8R^Nb#OZaMBu2ki1(bp;P z{d>Hx4O$JuQfh&FI9dSICFOU~9+0;m(nV2pk=qCiTdHG!ChB1F)kywt8d>Zv1V%t3 z{VeTbceYQPqmh%{!2kp_veYeOLRKS7-S6PqtOieY|AjX=5wv99crV&GRc@M>(FP6A z%!b$kN8G1`0V}#F8g(BP23!o4>b?*rW+2?Y5}3*X_Id8rq{ThmdHCWb{=_D04~It_ zyP9(DVWCX&U?jt)`JIcrka`hg6AQkV zxqbhw)T+(!S@f$yE5LsOs5A5$eYZ;|C@SYRk$&p7^N}rXeSB&=dmhxC&il_~ez#_> z<12oWJW>fEVBBYe2&-O_ldK+J4$K_;Zs*2v4@*`0^+lll|-XpvAL9|00{ zP}Ne>mALmsZy)L=kuGO{bJ~jb+$E9sN!o#BBU}FMOzI`s z1S7usRS&9iw~KVK5bXS$2!oUX3kZ}k1uedp*#|KhfsM$ZLB z_d!kExzX>XE&-8k^xU!UUJcBgqDrIx=ndQGOV|p>UTjp%^(}V^NT_1n=xx;uBxo`~ z=znDU8PC*2K4zTPS53a)N5^^K+j2DGMob(hzIE{JxEgQExmz#F!-w8c3Av!z-Z}x9 z?U-e`&^g|%28vtgv5h&$AI zyUk+Z&XwYp(Lj?@BKf=Frx0dR*Tb2vG%>5eCkwB&Sf>(Ji#^vtcvKWZ+VZ)5tqWGQ} zqMwj_2~b|DF-3J1+7@2&qh;9h39qAHDsl0}Y5JuAGzDrQULt8Yr^vtf=O1)a{9iu! z#gSX2YygtG^Ur?>%ZnBRny1dlh4lx5f#s_?gpKm)hGb#g)L6oJ#x!yu5e^`%P!;x6(+yPKhIfM0nW30jo8V(8B3OtEllpGK0EtI_aaiM*|~}Jr`xHSxjIh9PdjjM zO)z)3anOQ!BZaklB#vja>?gi~ME#<_#aX7m&>mkVU1L#ngu4PZrB5kgEONM9$v;xA z!8ac<$Ht|M`5G}l%-S8!8M(_?3wzIS`FfbMNr>JD$-yl@=kBYew?QI4r3-=5W1bi0 z`FS(iLb=(4L+hs>4Qijn4197DcPf=i=p>`3bzJxx;%4JyI^#;qKwcU9?tNLL2{Ap&TX~i*KS#y<6dx}JH@QuS%}&&Gd@sRWXMN0b7Y7iHJ_K_` zu@pVeD}s6w*dXg+G^59}y2!`N%z)&PoIfbJr~=j3fl+W#^mw-$new~#pyloV>!D7q zyxP63sB$Z%wpHg8Ecy5VT~jB!++ZqoKo4%t(V2$u_LYoFtXJ2K!=|}IMsgmHEwfxL zL~r)vkDj%(O7CH2AQ|v&%uOh5c?Ag)0S>#QDB_`}yay$O_Gf|6WTvdTzBr^Nt*}iS zLm`LlIa(bZs8+Mg=BsG!n0ZvEBG!_@l8g&ZWDClk48d@LTWs9PNKUjKAZxem+3d$? zGgH>r^D}tOOjMs^Y0sa;W!trYQ`<$#oGBSJ+`lYkGJFK)VEF0!sn)CMIid*^ zbrxh2le051lFHT^Rwz3sh`i^}RbqY&enqBH%xqNiDjcwfrT9x)+^{X*kCH(iuhL#< z1$^#HqsC&JO*N6ajKUgD&-a3aCVY{f2n(zGOm2 zMGH3z89_xIWaa3q2mvx~%m9&@aiB=%z3GMGe+l6u&DX03BIT8zOqR>V`OZW3HNDkF4 z!7F|i;-|B1TwrYjLtkj*V)Exap0y39{#_`=+Q%K(!liqdY`uJs98oV>J>x7HuGVN${Zpz6@X#@8n}iCZxNwjt=(kkTPb7{Pt`;u&f^u{<@kqi^z7;l1YHA= z-CrdMF(&+i$g96q2%w;9Nk5+%@fJJZecCK;C7;7cW~OZ=VH^`0gwHpIkED+zA75ZC zBtI$Zb|7TaLSjWN+uV>#G8AsUS34|O5d&u-YFx7Ka z;=u3F5f`Rb3H&91aH^Q(_Df~+*@s-o&t_9130Xu;H#awH3F`mpJ5k-vW$yZE<}jMs zn@{M8P|q;6FH)1d1XS09q=)6n@`JwWMJBJ6RC-oj4oTk6wuN96d?uFnW z%0?WJF*m@jtUKOmx-@|KJ~3-7=5Au%jHE<5?xYfUaGK~7E#K|L9$>MtT`Xg^#4o@V za(Lqh19aIxAm%^+Z6x@Nm{mx^HTF(wEFPSu2LjddA+i5rvC$SYu7jkiRn$%D!W_;! zhX7~T_4TOW%>n7517n{BBnNyT@*8gs)b8{iNtW5I_CPi#rWaZ z=)Xxl5!CXHJ!@B=ljI~zQXJ!ocOqTPJ;I0uwZGa;oGHYaSFXRVA)Zi@haefZ&SI9LMNWEI*X%qWY{iw$EDXohcr@!^W@mTFYydO+1luJ|C*rfLAmAkd;L=@LQPKzc z_a@*^0)Vo!c|8wb$h@Qvfl@G!H4vIIF)b1z^kjdbnipNW1f+SPl_xft^LvVy;r+LM2kt=B($SJi!rVC zIwvvxa-?T28m+F!513lhx%fGGHRiGfbA!G}vV<;?CU+2F%g!uVpSa?4$Z$W&s2Dvg z1hee+6?WLuB%{x(!44*`qgCM%dnSPV?`N5}MP3BtfXyIxiGA#33Oe>WX8Q=du{7?% zb`3i?fzOMji*bh_&#@IBhD!DZNWx)~FoOv=AHZ1^Sy-2~^^?$TnE3(h0qszKM7{We z_?s8INOKFN8TQ|$nQS%oDq~ zpJXK$;210UZfcK<1^8+ss%=9Jy)hW=N~C)@O}vUio{M9!Ol?SyQ~d3pv545Bq&(aw zL*&>?N1h8%!2br5oZ&QTC- z$9$TdMvPxSR==kSpmh5a4lil%FpvBm)uH|c-x+X}3_jHMoHXPSS;OQ5gE}9f z6toZTbx+}2HofbS5G1nTCC<4xTN@E-u8ZcG{ zMxY+V_&wDC0xAVi!JbNMqJpU>~y@Qz`jXT+-l z45}=H`D8F9z(5izj2zpjBJO*EijE{^KLEO@Xm{8Y>R6&EY^Jw`l7yF$&`CwbUSCw$ z!SN{(-V&mo#1Ko@mdn~Ijh>`NVgM4Tt1vFeu>)kWK;RZu0aHK@UQtGAh6%}iGWGL?j7Cet^_DM7~5 z0}{`*#A`@g9Uzv3;fDB463@1wm~9iBp;hn0Kj#@m!?)J441Xc$VxYg08b160i*bDRPyT{uK2$ zbQdlafU&5P;#S05>Hkc!-)erHEax$TuC*NLRlUn>l|4?_xrQuP`X>kqTe4S3Hp7yw zBW$uJ%hCOl1ngspUL{dUgtJ_#90kC06A^j?!H;s#w|e;IOJ3c~_zbKM?ZODjtER*C z;-wL8R8`xUG)~VO^}vymO?)2=Mbz~M%41T4|4c_daHo24ZZFFT#d!~YRZxv5FS#Ao)7u2YbU zcdDr&Oge!RAamk1k=vNmlSxPLQ-yy6RtuBT$lII9dvJ##=@};dok=L;|6%P-z@sR- zw&8>%CWJr-h!`4 zf;%WGDoQ}aY9}iCL>(}g@4in}_4I`Je*gPjzj95w&sL|lQ>RWXJxB7$n+nvY1Z4+y zGLIjA?`1+1!CeB!RD?ovnVtJd+zT_27(T-@uHpyAN^$}Z5SmNqOsX?EG?CB;3Ecyy zGd7MIeWGbs61s!XBdAnw4Sk)^j|nZLUg8Ag1l}aHicow>nyL*H)vW!^;xz}JY7ddP zlEi-19wxM$P`_%A5PBA&e$`eHI+oCVR2xj_KB{#h6i52gq1qkWy*lP_LEEMFVlH5s z1C}a20)@{L#KLWgI}R}EjK_i=qXEBdY@9oy4;6IbxB33y1QB^eXeSXNa2>ViNW|aU zh)9ZBr1FO<(je5I5UNOa#c~@XeCH>c1NzXGi zlGMi0CMiL_2c%9acAHLRX5zqEXY~q7&Q~D#))vNp%B#V}Njl%}jg)1%70-jxw97L| zb`Hqw`A-zSWFL{L-A^Sd5_?Utj~jIMCN~5o1lAic=qo;YSF5jJ4g^N@#ikv^W>_@% z1HN-8>(}p?)jaQR5MR;kMox6mX!=>Ce^cmLG?LV-C8lTu`8<$1DHaX5oQ01`pN*UI zcwN*TsB?)}#wBEn3dZFcScM9~Fy^69OOaiI#URd5`n)3ZNHx z8MfgzaGTe8B+UWFvZ=nXyn=7p>-^AyzcGlv)~CshsQXc?0x_j@E0ezrNo8>9R$nqHYoH#-h2-Gk ztKqnv97iW}K#$-vNSl%OMX7i@oo_TK@-~5Qv?9>)tc`f)N-Cbu{0Pt7nzAUBeOET& zGz?Fa&Am)&(>LrIu1 zYK!ikeTORL$%b{u3(E;T`(=Cg6Xjx!HigKaKG4=U}kJ{Fe|nx*fO>u zm>v5t*ebT(Y{Y9E5Ka9S&0?0s7eDbqPo?*W2Eb-@orR+@aj?igh{W6&$YP-u0P0vF<)0u4AT+1mi^ zdJ#$-CKBx7no@~DRZ~W4YHW7n5N<_g38>Swz%$ShD_avP-vme1AtV4+?0!0as1#(? zQ($hIBDksvPsNS_LEE(DK*n*2v~~GqqPW~c0oCOPv(K4?y5eC#OcCdhBwLgCMtN>N zvLqcy!b><|VWgl1z&l5E98v0Y+0n)#3i53rrCJ-r;5ZAirQ);=K7jJ>)bhC8zu;#m zWern4k=IycrnB(QrbwP$H~E=ICAH84$;U14jk8Zrf*mHXsY$SoB0{fH3M0?1Gc$UK zJ|@cY(Q@U`2)9I`_2i-T;8O4g#dDT=cdnENuS#>@0gbOb?m5bohag`8QkRG9v9l%1 zZ3ymS;B3hXpdwjPsg)$i3q47qp|jw6U-@*WyrN|Gww7Ix{VY3n*Xaz(U63sS))_26 z7#Xzs^`yL?|7M})s?Q$9UwVbo-3On{GO9<9cdr24a&Y0?T?LNtngT>zeJu*(z7*Es zq*w|H%W?z(Hxgi)mjJF389YKI&FjP>Q=Ec44@h70Lc8XLcJ6Un2-+0Ch^(_G2nO6S z)z>R$p0_uYJlxvutG4e)nsfxoV~;wW*d12j2y%S|1k`2gmDLF5)AL*tJ%{GXeVVi; z^T!i#7XX<4VWd{u(eZE*4+eZW^}>e*6A|N44}nJSm$B}STsnC+z-E!w9M8@UoJ5&p z1mW|8N(miA=$Zm=BU8yVOEXzwft3pJIGS7S z!c8OPa6;FVn#-#V<}_joMMiFQN>>JR3NKF|xF*)pd9((fpOzhb`s>%+Ru8wJyZT`e z>rS6QJ%jwU2&VeB!fMQ!#JnRII1K#H^2qkZX9c6LS<(zM$gotvZBYgA2OfC@35~B8 zxA<&gc>`;>My7)GRnNlKV=nOXeWHymfOAN9lF*&ZDI=U*UBu@RaRdAEXnHx8HFbmF<{-DPptwFBdrBh)N*xyld#KcbNRZnobm?DD`rU}sOFwHY z$7#a`b;Z5tj)^{Q3+HCiz6V-cBDWB*ngC-{$#GDzWmxFZ`@02s50E}v<}3(H z32W=Mgz_%Z@^JM=dC*!RK};3|ogduk-2Hz?aG`HWfiW17uQme@Au^MT2MIEZ}mA z&EaE|eVNEMReDkq>J*(UjlE~lA16;ya`J6$@`CK=C7-b9Pm(LspAxtFK$Vo3b{i6- z$ulI~qBj#Y8BLxgss<=u)|Vb(3RsZKfz(-NBb2?TUPrVgD!VkV6)A;@5_PLTQ zLTtJAv}E$Q@uUVq*T-Z&d=%?GWP0#K%&(_%(L||4zbbSQ`SSmT5650z#@Pdr$!gR4pLs}OH}~p z3IJ}8w$lQeD6BrW=LfQm(3CWo{p?7*lZbAD$l(M|3lV6J2tja3jD3#!&r(!JqV>ke zsSvwo>-`w57dYbtA2t^2LN{=Sd)Pogo#&+K%a*cK@H8_*trvzLG zXU8|aXi3b?z%-D5d7p%jYE_9ub6&RtV)10bn;(R{6=6vVbDyXiDqq32YW&WBK)}?0^6! z0}!q$OgO)t$XY}wYalg-JLq)=x)9Mr5U2y@3vO2e-JR$Ri)I0dSEhM;6RCctP_L9% z_cx_1$S;A^rR*-ngof4?zLM`46KYWJIBbQcNG}p!4Mi$w$Yq(j`Dz40vslEk^*xjc zUkcf>N}KI0JVcP%CJJ(r581}YIh>qB1ldPgiU4{Lpgl`1LvEdI<0BKmUhEel8D_}3 zr^#)tKN4Cz6xopS7uaWnjU9^Jm}e%@uF|wvT^!J?0WR-v`>cqG{9nk+uyYYrp)cDO z%jGPs32);$u#76SQ-qMpGOGE2+lypAg*Ykn=K*RTaID#`ICEv?0F%?-PX!*n%ymFWcOiFbj z&LI8m9z8#?288|G7)Kx-5Aw!+n|_dtr&+}^%kz^E#|i?~RhH=f#t_?-FQtHv2?4k` zI7?x6i>fKR&9$~z(5V}D{>5m+oi07&Q9rt|K?HHA;3!bk9FWp z7DGhk0;LywMe2?|Myeniv3p2Ml?fYaWg)l3SVga=fKNb!fl-!FS8l~ZN@-OlXt=(d zqF(MQ;!eO>&<5lMis2xOZb-s>tDkvi6XvTlbD}1}o+b#%}mXK~W~!+D+IMf&d_?tdKCiqZ{8 zoni&=fgwp2d=CXL!}4=}VVh9zeG>YJ34Mu;M$KjKV(zYC42&_aLB3`M#+g@sX))L`P-_^U5ntgPj5a^P0-n&Vh@}>+i^d*IPyg+XiME#2z>p!FGXi z^BUu8df*!Kx{5i^2+TLH&x#b=tDIo3zygEe2XtTq^#xF6PVj)hB7?ab61}N{wT=5> z;C3(HrYEj?6}hLHj+O%g+l{hGGYK?i?h31qVWJhGBMIg569emGE5T;EUJkLHg$E%6 zAp7}{t%*z(BsPcfR9J&L3!b^ib%?CRMj}Fs;K=arz0AJQ9ck(ENLK~AN;4;x0}Ia( zVAoDbaSs5#FySTLOfo{f2uO@NR%wA+JiRs*&!NF>vdQb&nYZy`pP$U(#$ zESNraZ9-!@5tA#J9w;lTaTkJjZ>7fCR}p{$z#Hbe<165$RhYt=VeX@j)SnjzHB>(Y zV<%B(Z#+t@G4!M8dnnqtL5C8sNB}xy!Oy?Aa{%yekj7}~Ea28#(NBMc!M2mZq@F0w@9iUcxW*67ss5k`+vUV4C$3hEPz32*QZS<8_{wa0F35eaGB$BacXZqtHkd zC3naZA}R3QlQMrtc^+o zpRjPUPOmFU&OVHwD3iRLUpNea#@YSMg5yR1P<4BR3Jt-x@c1Z7nX@UZeDzkb11JX$ zx8ACCGIR3%w`_&zI`D5%P8uVp8Qv2NqB62(hq)#C;wfZVP6W5n@IR~9sl?m?3_67s zBe3g5j4XP2!Q*Kpz5s~E**#S3I+n)2O|wXknoQH_ce}(tw=$x2GTT+XHd3?eL#Jgd(V-%H)~+Q z#r6@UHk%@^u}L`#b#xc?puGnJ)FJoIPJB8qiGy{7gV`AJItwTL3@4!724*o)i-6L~i_|l$R6)-1qbWS3BT<{YKxb=yaY{Xlqh@An1H zA1Cew;CR$|;Jkf$uCeiS|2rZCkB;TF(U-_t23Bo2ah* zo??$D_6-`P=UVu#EXDeiHb&lsR@zv5^aK?iu4#eTT=Zcd#fPL=0t#c@vAU^Q1u;ih^`Iz#^96ul#C|-G zt0_OChzUB8uxf$1%oXX*Gu(rhCwo_={x*=PFNl2YYwv+3BZABaQfI`4G4QPCXJp*< zC9{AX^m&yn`>w|T<&EvWI6X&r-Gge$Q$?PPIBwU)Wt`%~XNe{|h@2WD$ijVjIvU@*|TNDR5crf5ueJOw12_g7@Z|{QpGy ze4k(e{QU(p4Z+UBzR8SlS;iO{w}MUz4xwW7BE6(kM@%&^X6>Y26#kjeM*-Ef?JTH~ zrl3ph7b5>7iONy{j+XC2x+$@)oQeJOv$XRze15B;v9Wkj$u4f_;6jo&r2at>$B773 zmbSP8>rdEN9AVC~F;*QsPF;^kK#sZs0;i?cpncjXr*Q55ob4rl5dvJh?1J*2Orn;E zn!MCh_rJaj#EE(vD2$KQj3hS~b}Q@71PAzX^XK19auY)*&_&WniC2h3>}uWxcN<^v zE>)fSnTnGWB_|P21u-;*vID8y>3SSs*hJaF;rwxz9hcIG>LKFtB;VH}>EwJ1Nh(O1 z<~yCdYLm&gZE2Z=ehR3L5xe}dw{J+1CAS&DUh2^{)X|%^a8tT_uLu(x>kaI1sc}R? z5YoqBVfBEEyItY`2*P)=8KI99cQT=g?Ol2>#Ka0mqy=N90+{F=2kUDE9!P?G5!gd! zLA`uPeMIInX0{Kzx_5TwAaZRNL_e_s(yR*z{gBW#ha0n+!3kijJGLoQ%nHr4Lv$As zJ}QJm-%V-9#*NkH!ivoy*nF*cAxY+25^4W9c2=yfE7BxgNpglIfrHNjZk-7{9Y8Cn z2LVS4)kxpOrYFIL0xt4_dlB4Hz=;9j-y5-a??zwpZTys3A0Xmz)kRi$_o`bMOG>HC z;9pzha#rYZ($*Y~yJ;{#(D{)=KZ~slp8Bb}i|hkbi>o9*Y*C4?Kg5c-gCQ~>`3}vK z2pSD%1HXdXqGCrVN5WhhgoAKt71KjgC03?EI0%=HQ*T`)RHi{V2$xZDcxaGB*)(VX zMi`!;lbDzW;UHWl55iR`W=T@a4#=URof|zZWms+|oHR?0F6F4fbI~t3Y<~%ZB!hz2 zw5GEpZ-A)g;z_3w85E?%lXSshY{3_}36+ITSdGO=@yb~(n}nG{htW04U94l6>hTJr z&Dedk!H1qO|J~5MHgcwBiy(d4$XS|q2o-I7l@?41EJ24}nffPMhHXaJWH&;fwg3}6NU z-2qr-04EX95r8!Ya1;Rt0r0i~$hL7CL2VoC1_j;Z;N2Jiv_eE|5{03IOVPylKTU@-xQ0kG2m zc#~!#&^``vsyblQ%4?*m8`POFdD!(+wM$yDop&x~b!UIV>XsVSe#Fg$)_-hk6tezH zS(jK@?V6Rfgj{cs%P&jLx;*8{V&v#fdF<&F)C$ea^x}lB|GGr(Q+9D4g{g~p9GL6qV#wxfHVN~HcxAyo*`r1 zM@$m_R731uwry`=UoYFq?o{KKy+Zocpoa?QaXZFs7>8w~5X|$yh{L2^=CUj8Xj(m7+MlG2qS5uWn*5_crkz|#I^QNO$iZIHu`nhuFeA>w zk+2DV?Q1CIpAQq-f8NGuFPL4x__TKxtU)uj8oWi`wV=>BD8Ixa-X`K{AoQ*kELCci z-ywVn;IdxogUuCKfl7ZB8+W~eSWohqg37aAjlfPJY=f2h0m()Hm)^kKxiBkqENVwpuSCNnA$&_$c3E>tc^JrWE8UQ)=2O;`y>yCXt}8`$N94dmF?EmUY=FA~-XcXT+OxDNa#qwo3l0aokS^oZuxtQ`k4NU4dw9?c~QA*-YHX-b0$*?^)SY!N~rbn61QE*`7(Sn8gCYz5kBdTMxy# zpk^|Yjyv>S!f1D)EKx>a3NCYSZ?*#I@fqVR%BB)K+hUP6oGP=RH&hot-|&@zN=oMn zpKXfrVzRRzr5tRtwkaNPNo&b!TxGo3wAC#L+QbBv1%{G zs;;~X2$?#h2PecH3fJJ?tii!ot z9l*6d;57F;0HukmWj^?HmrheyZ+uH^HIq3w!-Sc^nJ%5C#I8mSJ;%LSpbTKY#+i)< z&vLI4aNc zQ8p+q1Zcu&sAM{0G7#``|Av~{EHE>=Cv*KQb^gsV=Up_up>cdX_C>6R5b@A((u4Ux zWrO`vrGHP3w=BbpJVV`(1vu5}tO5*~x-d*qe@37x{Dm(#yqHby$-F#f#&|$?&C5KR zPtozSg3M+$)TNA%DZ}K}FC#N#Wo$i2($_McMn<^)zZ6n@;xw66lq_vUh_*Z}n{hR|j+l@{u2 z3MSj1DIVK&Hy~yK-iN`l){gD*k8j9z@YHZ)3s&wx^ki*(3MSxw`dW_UB80s6KgPnQ{;tn8; zHSlJgb>x^U2p9yfGiC>VCSsO|>Z7hXU-w5Z+KFZ^O;t`69|bCeyrc)|Sgjl(?rp)m zjgxcUpKqccSvHtE$MO1|e(hnfpWqb@NKotWJZ)GFK6Hzt{QQK0p?Stf^Pr~Dr$D^6 z#-Ytvr^D2t4QPwyo}<_jj)1#lx2{EgXxEmGAm#vJf|bdI%0s*EbYUx0gIIeeCMAet zgiWGYx(?(h@gaa#7Wb1f59T2(S4<7GxYkU4OPoq$ z6B_b^62!8s_LSQY`6iIs&lTytt#m;?52ThJdq}vry-hQ>BlGpZ>w8@XAzh1VPt^I6 zXu4HIV3P&bPmMx@h;>QUbbm4pG6b7RP#_|8KJtmpGuVUA-KRZis_vxv1+Ic!Y7)S= z0HE-Ov+%}X$d|$s3_md_*~8VI=4c-VbZ$gO`>Z%s5AWH5-V}SMh~>PhCE%C?H^T6l z5R@F)y%GevASI>mQcX&NJl9Jpb}yvkPz!ExJdAQjP_Az!4JO8xnVj z!mblxEEV)iuK}D$)OkQ*Yq8CYz$OVSOTCIcBj}t~)CAHW0i3V=9)NEkH6=*i1*kP~ z;URezkPEx+UU>O-^MU~C06>N|<9i(HR4Ya>-vJ|Hu-Je#1!uu0k|DjkAO~@mi?E#P zH9#~QfIr{H_~mr&bs+a;QeYPoHb6asij%1OE}E-u=zADgbV{dC?a|4s0vn`RKbJP4 zX{V94BjCDhBvaQn{-euAkS&4KnR0s}Wg0URUBJ+Zfa)=GxtBI8tOhXp&{{tq6JC?8 zofaQG8x~wQ+#{pr|Md^Fr&D7-$`L51B8%a!1GbT88@xUfhe?A+>_mBcp_YJ8V{P0n zPJtX#4T4Raf>L!3RII5@M_Di>q2mXe%n{dP5`@D+h}8wUL{qXR!UF?KZe>bp&9IG@ znv;jAsq3eC7ko%!Z2`RzwmDr_nH$Y4F?P zJy9A-$u#I>N@PBvlfehP-q3D={m7=5!^>795^G{f$PyH+&e(ZqAMPS?{rpV2f_sMqhbOavv3Vo-e_Chi#a`^ zA;pw~->Bp4Cpo`N17ox=4Q}>;WceQRtrXJ73f7I(h&rl?=+^rbCHLXwQvR_>6-`Os zk){rpH@FmV`*bNt!^sXTV`876PNWpPW@FlKcHkM}U$A(6^DlLsf4Xi!*@0(Cv5>X8 zfmP~r5M|!bY%TH%d1;4IK*zJm=<`soL72$^ie>=r_`rqxxik1>Bm)l)29(t`8rudc62!Os{qZZKtj0JPF6TjzkOHsAetZ(38G zzNN$nB>HtS2GvlT&gj!;s%<{CJ4`Czina43-I|aj zV~i)s@klt&i2ayUaEz5F2sqD(?eqx5*o+<5?3j@qkg38Zamn(;Bkh6q=dKe#esu@D z{0n1G(#a>uO}j6xoRS;fQwaB^7g4uEglTK=g>tT|*}&FoNo3Y>nI-XpXF8LW|Eleg zl-x^{!{}N{lf9cM4kf%B#d%-!;#}t_48j?bt|gQ?1@GwqD{o9l1#6H~7+~7xIiCzW87~|3WlX zI;D>$dnf;rG_F>`==ZNl!-VLzYLdR0S-jFFjW)M$x=)yN%}l4Vqz_uU*c-UUx>%&# zaB&h#LR~=oF533GtYxzsBU^k|+P`t1%FmPG>6hIY@LD_(@o)FR)VkpxYuS9cY0)M_2&d z@XP;t(!v>EO+39+O~}L~RQ*#X4o6nF)+tpZ1Qau%>Xaz&#WNE~@|CJpC_X&pl&Tf_ z2^*fD)K7V(>V7;~lb%8Dzc%~6rI;D)>0SkjQdN%McZC2ACk4w{bC6^(TU~}fdgXq& zIv39g8nd3yIVsGpbMqtM!y{bxc^Orh+H<*Ht%F!nrw~{!j0Fuy7aW7$r!xCHUlwA1)aFKf-NX-=XY3b6rZ2q4>T;GyB zg=lJ{I~j63Hx^AAF(e%4$SUHclJhcyW8{0Q3i}Cg{)f>StZ?%Cqag9Ad7?WSuu{cu zvjUTpuW|0dg6o4{brXKPnLfqAALJ*k6UROfmT_)=OLB!gV<8htOmp89XH*0588K{g z1>cEDeEu?yE3V+Mj2n`4IosuK5*DXV`Lo?c8W^`_e71WPA?i8&;`=?ijO+CT5CJ~9 zz^y$RN2!_&ipG*0w0nGHH1;)WqHjsAdJIr^ATVCRs!ssI@-Pc9MLva$-~FyD2awXeqcYMe?!rB%Kd4hD$z*gGZ`?q6qvVt;l^8v4SG>ZQ$Nk z%=?MBOAw-nr#dfdcSC}}nx|FeK|(JORs0%0MDQd5L&J2uB{VED8k%^5(Qt^0?no+W znQJ!uLt}dz+H`C(`o@8rj0tw1N{S4(*vY zQ{{Ezbq1wC8;4{`b9P}+-dbWzF&Y|7S6gXsIV;&^KifWRLq+1WiRU=yj9F48_*z~E zgp=VR_~~dIIb;7vwyb~s9x7(gTdDUk&^st+XfHx5m)2cNcwfTPF!@p^TlhA@+ZuSD z8foF%3E$1R4D4%dD=1a7Z9jgPFt=t~8vo)eg{3MTj5hEfa=GXu>AB>u20zowQ>cCo z|B3L24Lo0cXyLL*wg_+zo3OkRd#I_+&Pd7UwG7-(u6K>sY-?%M5Owm5I{8$m9Q@YR zZ$UrwVk@3kyt%xClj`KCDHbmC$99C{!(6$F2Uj<7b&iGaM|h!4EGr{rRMYa!OkIxx&rKBgz6G5l z>gWv#Qt#4f}5lkFGCLyo%EN*P8eLp|x|Sh!5T3!9Vv&_2?8`lQog5Lv6V zg;`Cei97+(3gKS~Wtqkdf$}d0p5x^ZYzDFfI8~k29JqxV)dUR3HCG%^exl7NtVI*S ztz63z2+SoAYQYD-=+`@UBwc=)|*Ebbr`LzJ;YmwaD;- zkpW|GvdO#PJ+y@s+THGm6d)p6Q;R~%GS+_=5!pa^Wo=Z$7sLGd6m?V8rG6L-FxXP9 z7nr!eI@_4iz1)Njr7T56W8g1o!dXHOGy_jj2f&i;L#4+DqmU~iXC5rMzOOGWhw5h7p$In3YJ^?HFk-`>Xs^4 zxd20Wuh7_p*slQa+5=cHUo7qYK?~rQ*#H~PMsPLTqN;%KS`;)7@3N5u zUY(Pr9!853rMkl9cF&|zD32Vq!os@|K3c@XWy8q6K@8e;+mL-UW>Z8#TpypMDl8LE z7rJdVQ_sfC6l{pC^~x{UfwZNTb^vMlVJa!tR)&0+q{3MW%3cIuGl(%8X4;`ky}7cQ zjE44aWd%co0K&%Y;XRoM+>K=76-eB~eD~>-mi$;vFZbGwv-IBlx2gxss`DyBv1J3r z2(bv)q6JAS!)yZUQm{aT@@^4<4h7I&XC?((n1b)T%5d`|HjT(N zH25{xVakGHO$;Cd{5I@=^BAxrfjqfb4Ht4_gFSN5;RYYMB;k?Ebj2qfT{1^a^^xP~ zq|dVInaZTi>?&s3&8P&%7EBt>VA=B9U^vzhJ6=wB{em{*MEP|LOLQiQV!xs+W_!E3 z1ooxC3e+T)7kAh-x}36ckNnG_F^N>pqJU+FIA4gn$nP|;*i__NvV}SoHD1uefsS3s zt@)>irt?Njt@POxcbXB$Z}^s~4f2}}dTZ@1F;CyRhZ(WmAQn?rwG9>r%ZchM{Kdw6 zDTU6UVPi>@Q3j{_QcS$m*L8n^vW%YDS-D(i_8Fn(sy?VU57!asjb3u|*ee$6Faa(9?96$6i`m3-B_+*( zBy3_4Ed_8K060g3ud0&yHw=rofe+ZpJs7kL) zS>mpP65N^67R<8XtjTU9*+h`>ZdBdSU;P}dkaJC#S}B!9q&XBcXyU0zH<7ep+5_Xf zI=0YGdT6foVQN9w*BQ;+J0LS*L$uF#;hMCt%1m78dlS>D0ZZlBJY15Qx*iF}W&|WR zZvc!s{15B!bF7L_gX6ex093aXyT$_BYoH?KGZuKL27bCffOlBnMF4V#q0Z@IrhXh1 zma8bFGNK@rVi4pYAkCJiOVIQy6Sa5?c{72wwRnnU6wL0JWt7C61xrAW$I^gk`4Ku2 zva{e=K=mb>0&Ztz+)nAQSQ)!;Zd!Dbi{EYqI8l9rV5cg_?~;=yg1!Q1oFV7=e;@P= zK;=VvR@5C#;ds*WR{uH+zLVeq0?xyC#VzYg=N6xjtNuko%R4WiSyeah@nkCW~fk-N?qQ6aQl@EiY(i2HN?89USo?udA zkyPx=*y#bu@d&)3wLP1MHZ*CoX@cDQ2H*(<7Fpo0XdM8yVQcGSf#WshYy#VBVEJRQ z$B+wKH_MqO@8PT*o3Af2@=z;?dIBg3tJ#Wpkx*VICxJ$O5=+h;>h}B^kyi+k*B?oH ze)CJyo&`A*NYkEY!L(z_gm@zEt%1pWw`2z^uCioDbw12^WlQcL>kqG{st;es@4)6a zL`>mdyv}3_AjvG;?ofZj;cYD05nJo)AacXqPTUMI;OA; z6sEbof?%@6y-nQBz$N;?6C2Pz`hwr(X>v>WJ_*kSAzC;ZVR=`J_<)FUA|X%Z!BH($ zsc_F@_{zivyHT?b*7;!9FI2MUDI8_`+n)f^_J?}61qz99)e zRa{wIKp({1BWy!~nES4PD#k1e@fjqBjon@7+^=u%O^Oj}11^+<4du2ji_<;RE|>!a z(?eWy6o$(d)wIaAQnOvSnv%DK@2J;B_NWxy7IiPVt^JCz`1vQRa#!f^_jBwD< z`#WQqv>dU}A(r?D5-%0e`DW}I@|hm}F)3YCvN?7hEyAgxDP&EnSi`k7U0yrMI$hGq z#}r;u59M*izMoTX-RpJ>KXsO_4R24q@YA%u8^bj%7pITuTe5j^$!a*%o2^Q9WV{=U zX!L3ZiWR*T38El(RBJgnYp84V!uQg`?tXuLh2Gl(QqXb3yE!ZPg(A*_2eXP77QBO7~1; z+~(pB=HeJA>hk~=gIY#gK@I@YSWM2qJU0)uTB?S;|4$>Xjzx$e9YaZCDqX4$GMH5L z6MTdO1_y8F@?v5BZ42WHpHuk9qi@BqWrSfR*q~A7^ zp@PU1y<$v4Z_|(JGW<0ZRec`JN~y-w3TJ!OcV7X{GweywtS<~yEWVGt>T8PeMJ|%q zc$-vniF^nys9Zf8lKOhHbF|kiexABd#l%pjm=lh7b0S<~bfSy!i_Hz#G>zLO@Dq;r zt(X(Kl6|v##i1cwveS?aaO{$BycgbA6H!=kO6X)DS`jfN9PeE*Iy8!iuAq1n2%Krh zH{8SV9(Zp@MCXbgp>99`F1McatjN=dE*0BD&jY~`5M6yFEV+Bsc4k4g)R`$xQqEVx zZB}yo(i5NbJO!c9yCZ5`;1U6`m-Zve;}21^xW;4w~#%kOjMt;ZovD6MlHv zFovXZ)Nbe_0@}jg5>2>=07@eSGOxX!*6*-1KjR?=?@V$s9xpaR!rVYP+>v6kYhsV8 zClrVsskk3mPXJ}r4ijj({qBQWW)#vIlx*zQ2d|hnHGv$MRmws!noDJCiSA+~!a+~x zLI2p*7l9gY@>$grUW$%Z91b?@{Le^vlY?N^F_>6jD8qKhQZ)|=>%2{b!=_7u8>eE& zt5d%hRn8dQ)nXjU4x2_Q1tEfy5cMmJO6)9EOG78qc3W$7z})?}nwByTJENuYa&(>~hgoVY zxeKhc2K5Uvsf&@RjRIE9HYU{8F3li!T=H*r;BBVz!gpdhtN}FU&@+9gTb~_FQTxL_ zCt3@N30tQ@5t^HezZogZIWXM_k+C6_8MK1V%Gwt8`*CQF8<^xson%dI3xuB3kx(0l z<6A2eY?0*!&xTd?^4b|c7LS~vru(2|V(pmAmMBwz0jq>iYZ>?DNmcb!N_aj;$&e>i zotogmsKEW_>IDo8`e`+u)C#sSwkiC}RTqH~*^IR+x)=3daYCpl*0P8@A}W3f;WOmW zE*BYE2tyXTqKJ{EikYDqAmR3bio-*7h9phRBuQxzcUj;Y_LOpuCc$w#k&>>CCdr{i z4-#Gw>If2U)-d0;XF{2(fF#+0ILkEUTV|?3mEf;8Xv$D`JthmfTc`u2hcLvTjU`Hy z9S&Vns{Y2Eb(4f%Au`Ucg*4?QD?8Z386Z4@x3*Vs$1!2_7mN&(}1>Ml(7+=cK= z=n#*BP$zm6erbHpMrpbu@Iv3X)`{{yEW)>f*X<5?(U-`G6ZrzsWhctniS~4`u{K_P zJ93U4&N!Bdo%^Xg{ui&lOT#c0#j9nWH>Li%J!YO)Osx)wWQilYZ(*iV6k(m86GBDA z)hH_SJfYk_g|@a%%|vC=>eQkBQ-f*hY&2rUlZsUrp+{CC zGd!huB9mJIzrmeOnKy~d5?XR~>?x2~=yLK7~2KpJO@ADBppG_!bCaIPIfgS_(wi z0T7|z+0B2WA3a{henzrlDHf%=_wjNv93n*;>z&~2ePsQ3#sMO&7@Q6779Ot!g&(MiFB2e55g}e%m0OWar5yKj-TyB zG6dJy6NTL>9G~GtzC*vl)ieHvC$~xsg>cmYh30MnaX3D+;!P*IKkAJ#`=QF+w*=na zi98Qu;Y6=$DL7=7MU6i{Vo|J$MaxNhT)m1ib#D=#i=D_^Jb(wkjYICE1_l=4NWK9~$dwSnC;A#1bTBkNPb+6N8CiOz<#j}?aFBb`Wxj?BT9 z43svCH^YfMiwru^zmZ+FovVwIC3Q7gnzki+e1h3i%+(Q)AM2_f0VSJ9x81OjG z%_Hp!v`0yBT!Qu-(iRHsnH2+^==m61nYrVf$k@(IXb&3~ zcyOYhTDo7cBxqFMOuBVKce)c9pH8}y5!MuW?1g;|EOftSLWs{%ABwGBVnQJWb=?Ufo63hWI_Z01BIg$O5aVPpU76X_b z<9VuB*lN{Q^kPV`v(dR&(YS1lOTZVctB zBf0h`S0T8HZc712({dYLqL;|B$aYK5tl+TfM3CcDKHbvDUPr>OHO z>QNCjNkomqui;dspeR)(V0Mot-CChLSm;(DWCA~;MnKnLOmd?0(KguZnFCeABskeu zSAt)AJuJ9^=m6R~J6`g)L*2U(L=$~PwJOID)v9iW=t>Zw{3szCIiS13q&Z1|cc(5z z6O3i^IaQs*CL4w63C9cIL7=HRQSQeTwQi$EGx6hIEEMCNNNcgl^bv&OG9WRIGNo!5 zEVo4HCODBnV$J&DSLntHU7d<<5&B?`Y6~6R4nlsk6FC6}$cYB`8uQaJA$BIjs_zhV za9#Lc;rLN#qT+~cz^};u8Azi;Dv4K+c(o9p<3yeo;zup<8X(0mlp|VIi$Y1^#m}|q zTNs?NtW%2xo^dFrI8}O^L zJ&yK1x{5>o55hIP<9a=8uu|?0i(wB@}cH z1zjS7u5}`(NzzmB3+>eBAay4Ru7?vjS|0j3(dV(nIo1w=JSS58H=?%j?oRX&42Ck& zcIFvRjJVxHUA*Q$8flpJIvuW%`js({JgMAVLBZsrGeBpxNv7_*%=fmoSk0GE^UhF5 zhlph&7+h^8f`V)fq)Y@6uHP*4!`sO7(?`&YU!*&_96K8|;&vi70>Q;AEFzr;R^Tul zj!m>QcaY{e%Y0Nhj@@hKJBheG!Q6-pVc%UsL>tu$d4Q$aqIR-rv^$8^Iv2hO}PT7uL-X*ss*)N_Aky(IWJMckB>;LC{wcSBc`;D4CliKHIQ1Sd*@xlZIM z%sfIJMAkGQSZ7~;34#Ga(AJ4`5{+&b<6$fx#n?)$V$n_eFsTwBUuh~)kYj*EB}(-P z;1B>%ecVoSrW3(>8qC)oc53ZY{VD(#zoI&e3zMQ$mG@~P)m2RO`wx;*?Qc^RJSqelMqJ*Tlf^L zp}1p{#ocVh336aU92zX`KK`k*K1VM~QI8-ZZck&X-RdeFb4c$ z!MAfF*Wkg4mf_dyolgm^mD&wb)db3%COjRS$Y|jy#xILK&xs5XK!5y7V&gz9Ee(yn zPAx~fmiCv&kZYZK83Ntbpv6}qok(6iI|0v!dFl7@(pUE}@r{`FyIT$*LzWYH4-c4J z;aAeC%>ANPI+lJ0646p|jiiQRU7A}b8gC!>GMCM2`ms4(`4x}QPbNJd;La$Dw4z|~ct`Q4d zucksI&cGr=%o!6`S0*LANlaXAH3QpN50mSGB(%Z1d+MtD0lZQo9qshZ8(pD|JM&%0 z%UOar)$iECQnX46o!Sq$6< zQR-K;4|OC+Vn>K(70W|!89}#h0JKoDz}tfj^fp3qn;J8F^*gAQY~&#vKgfyvh1Tyx zf0I67Mv0yf9KexP>3e;pamEqb`iOj=g0SdW$?EIE`I>OTtKNhFfH87^h`Qvtn>-JY zhql~_EE1lu@R-zI10Tx^0nh!>U6|c<;!%@-8u(dl&DLh^zO{J_GkE*kwl=wZUi5;b zd@ZzdqOT%)B?e1Lbrd3P^{a#>{Auvc5e7HgOZ)m8c=bMh7}MO@R2!(AFgDwdIZ zDyg0ns$+#}Bz`3u)2JLQ&KyqL3-RI}0u;7z!2cD>cKD?W*-@ljKxr)jD!N6a)x(o; zqQBr5%{VHcZFDZs`VghZn*R5kI;+j73$M5HLxZ}vtNqco)H0A@oDp_A^C@QoH8Y&En5l_;G_svFHt{(Es2!bQzlF zYI!{q_3ImU=78E%M1*o4MUTU{%_=56C!SjnoR*2_7C7VR2Uz9Uq8e*FzH-dkIjTPg zklKb9w+?}lqBkYEFC}KO5x;0*uM6lc0lk4=X}jMDyG)uIwn9SJga)MlR}JQh2EzBH zWMYRp1R(cP2oA^3cOs`tI;TiF##r7YX=%?|t%03W1F7#wVF@^q9T*rw=d!E!2ONw0 z5bQPn@qXqond=cCa2ruP;rIm@Y4PAhcjDJ$>6lS_fFE zYUfXD8$eRMj4U2N#v93an=oF8Z@@@e*Z9+VKEaZscAyZ|6tc_^mWvSNfa~l;m!YG0 z>Rp>)X`@z5Gw%gRH@#pRH5klI#|F>uXlA7PfgS#*H|$7tjiflcVv!Sl4Kom? zc(J6o8X9`)R!WLe{cTjuI;cAc5VuH}FLNRX}rxU#kuPBRMKw$$# zmO7nd&01#TMqr9wl5AXoM<;r*CVg9z?xzNl^iGnVLDCgMx?IAU#{wW(JPX80?#B%; zgK03J$aB;6FVB+7(-o^me2djt_7mH~h@l z(vVQEV7lrC`LytAK&k3M@{C}vx*p_80pmU|JVzkLA`c^+=&g7F-%m(F_>L%5b*KXH zwNNLJkA>)7396z+lFbYEvT;6)5QL&y$MO%`f)05uy!>MEhm{GQYU7@18|3qdVZ zzrh~4-9UveLSfv(gA;9uUnp|6k;rxcC34i;pjC%Z39i^A(?KO8q2dy+dzuJo10MixdFWb}#@aVzmaRQi9S52SCgbo|!yLs51v&RX6xpSM zs#oPmL}gOBBFaq@xviYYE<~Z7=uh}X4vuBw+tIt_sOTxw$07CSK;sfkC$d(kSL2tO z4E1Yrj%4y(@E~!-49eTXDkf&CxhtVpk)U!tl%ACSQ4JJ!U8t}slzm)v>TQ^iB)|s% z#Bet%G;|YVAJa$?0=iVuYOu3hE#2rzaM%Q_)ey9w$N|TcJ~gc%N=Oz z!%<{9V@n~TvHU|d8Rbh~W?K~%q=CCuFf_3N?ub$^eNBp5T3~Drd0ldbl3XuBKU7bF zQEg$g<(SPEve;ALIh=vAv1}F{fJ9(x!;;pE}4(;XI_E zxZL9|7NO;s|KK5XJX##XGq8{8Y9uSz3jz&B7fil13@e}b1Cj?Zx- zU&_MnM*Kp9zEm?cn4y-E@Nc}i{IXIwek`^?2;o!swUNoU(azkzUS+Ja@Y|GdUDme+ zJ=7;v*rlqLAjML}fR8(01e7?Di$%cs_(g%dsa5Kr4q-}5NO-Ccj&>psiMjh7zaYFr z6CR*ikT5_(ZnO%=k9Q&mi9{Yd0^!A)FkgMezQTfWGlcL&>|Hw!1miTpfvSoGok_3* zOU~i=2~K1q9S8CdiB?gNzPB^I$M)=R$E}l)UhPZ0wx?E<3zZp-HHB+UuiNqAXUF10)dvz z9#pG_fjroSPeb06?t(|iJZ2>bUj(7c(?3N^CDo@y*dtchn?S3_{KD#}i3n3~c*5GK z`f3oKOJTDqY=H>lBD52of?p)}9FUBY;NWkG3KlLdQKjnR*G!x{3wGSS@ns5B(ptFP zW)Z3o#n?vuh{o>bQ|{v;H%;X3MZ1t3cZ6j0)N%MjD>n%9d3LiC$lfBDr=9}4Y6HF9 zO<*Z{0x~LI!QPQyflpQY3tPQ9NRziySCf1zpzh-&e@2qb*hQnb7ET1(#dec|V!@^b z_gACI@+?^{C(ANnIRlSQ^i=#Jl@|=lD`aT_miA=1nk+|?OAMP8?3`caLNiG01{2RKFWN?0#dNWnWH6Q7QBBCGzQ@_%D)1?Ag=0e^A~ zUk}T7J@^1`BXF+zb)X%21Tu=2i*k$k8@&O)KyIa!)}W7Lx{g1uOGE&Rd~6=vX*(F= zV&@nAM_3F0z%-;C$exnKgI!b}(PN4zt>Q@O4U3IJw`mDo)Ne>X*0bnFl3-6ixPzLz zP<=sEc3=?tzZ-m!?MiRDJc-Sy1OVT{-jat*8x!Q=K$_K=1EE3{4>NFy2;1f+kvSds zq@84w3H@aSx|7|(&K-mNU&Ya0s~?ixma2}=kLl-HK0l?OH}RRf!|-jT^?c@DRUD1a zAg$S|Xi%I$Wa!Yx;Q0~Dyle({Q z2z6H7!Kp6(h&Cv$&XvFQJPM!7ZEWn?<6iRJHHa+bFiV(=H&j(&^Di{`<6vmOUR)s! z3qh@VRSVC8{UEM(z;rRabycf1`5lKctzG_{?xIM3S;Eqczr%>^n-IC!6S)K;!zB&r zv9;;}gm%>3{8@${xh)%UvAFsT8NpvP?li!Y@>79kLy}jqwq_9NlF@U3Q0IskOxLjL zQ?HhZ7`!1eiR9KY^uNUtj>@JLW7Q`%t_q|eM5$_@hpbdA8>uh&wB&C* zeaNR>zvF2wo`UVwDgur>4uBPWdJhY~>PbGOevPO5tb`4B1)*?Y#_+w@uXxXzZC#8d4-mj zu2zE?89*jy5X4NbeN`UPR5c#Re;KmROg27Cg!*2jgK)Vee3B13ukZ6w=XJBN?^1(= z9cOOHp03V92t&7kD*=Fw<|(*$Gjh=m@n2R|9vqH|BaEw@ zwZYMAId;UqY|Q-2qaOI1e5!!PEZ(|2L$3VbrNG5FqLMy0qY7hEN|D@{nt|DUY6|XI zLUjlQHjd@Fy%>@VA(g$;*o-?OsQtcRN{`o zMI~FT-5d^uDqB+{3=Td5ZjA}oreW-Ck0gyDUQmeI#o5~LD@(Rij^CWR-Z1oq#7$M} zd9ov=dJX@yES+eXHuuKoTKd+6ccc8OS$SjRQ<3^j$-ZL)Zv#?T*+Zy|WXaMrA%YtsERjt}^(><0wtY6hEP> zZr;O|x(U&CEld4|(W0_sLu$$9$_$pc>?}E&N^E=@qyv7WfZ|JWr6=>CJC;d{_WEqPQB429F`+LkuU0#7<;lvvgud zKLs6o<5{f&S0IO%*B+`Wu-79njL$9ABFxn|ss09k1IH4Up~?joSML&bJYfhY;Tbw# zxMmjAUicn9C^C`hq(C-wIx@-`-<_mCk@RUQA8Du-OlX2ms8ED%R+p2=B$OjCeD;|z zlTaM~J_Op+g=$@Rxsd0T>a@W}VgtA?UROs_(H_HloL6!Bkl9i%9B1y{1@Pb98W zH2Urv$6)F6R2EA|HRHDb^+m#1uaq52>A{m@>nrD{_u-MDvit;iN^C_2p}2%?f3`-D zqg5|QJ646y%C)art;G3cw9?GrS#pTi(;AaRW(@6Ve=z;zR)#!u0v$6DrN8 z)N{*^w)Bfg-`+=`UXCM1T3^BawU@~jimd(Q3qlBj>sSk~_v4vT82GJ}VAz&WB)`mF zIiD)PLdcac0)86c>uSa@6a0R;JR@IjpuSiN6Y74N`go!^^9{!ju2>Kn2I}qvG46vd9mx>lMu33n zM$BIPgyZ8Yf}tY-no7`50vcJ-CbSbEY?4fIzZB50ij(zWGk~WNyhgwiE50;nNG-7Kil6_)~R z{X{&&{uuta>;7i{FwJFogYF=5_?Fept7YYUXO_xFTIPskHF_qxoV~z`VWBMbJ}7Nd z`+}0EKyu~$e732QI06t}r_53>0;O-3DIdYB+_$ETBru$AM8@eKJQt6-1}5 z!?`8pouyDQ(K|~Gf`*oR8@a#3Fk3mF?GWv*tS||;)`#olEIbZIS>M4$4|4SRObbip zJ76Mv1-s}Z@q$CZjD5HZz>ROH7nG_?khsh1cdT@mc=^ca@&J2)$&P@>bKGA(t10*h z0nca(?jqpRePBh|Spa9G!`0*IEm29pzwIU%)sYPT8sN(L7ePpZ^kcyAF%rh7;{uIQ z?s7o2wS}XEKwf1@Z320lh&kDc5r!K?4C-OwEOaEROr7K(C{d=GrW>EiTlgu8PEcck zx^AuLUq$4^Nu_YsXWdB8%UQsCi)H=p1SV+m_bWxVWok)9D&Rfvwvvlfz~2klU!(&5 zP{95o{e`k$0XVrx1^hts;2Qw;6{(P3OTjGCU?<&JbiwYT^izRru3!Z@T!eWAE3m^v z7?xd-`*^AJqrF82E!F4eA z@#E$#@eLJRoTJ+krqTGwvd17TKwwJ%3$N*c=?WNe)KW$a+DrE;VtD0$Y=D(Qo9dn= zQgrt_v^+~+KNZUf7U%(K0&{LsmD{uX`{>anmz!>V8tA-%h?5Y@Bwugc^C$DB6G=s^ zO@P|~OwjF*HsyW_P~&o%Aj>Y`RRR_R6B7f|0ArMcTz3c#fSMBiGakOWpZYN#=qz{$ z`IASq>Vqi$3aU|ziCYV2Vc3T(Ao3JJ7QpuLaDJ9rh90af4}U`n|PQWynY z7}tbeVv;NqJCbC@`y`gD4)-Ot6<>z1GIDUWl})U(O-!zv=4HW>nAQqOz`2y>j8FUc z*?xrACN23WCjMD{5*tE?p8Pi~Aw%cxGE1m4ljn8@l*dRSJz?;1n1yCvibRBCB8;Fh zc+lCaS%j5K$tb2za1)4In_gN)B<)^`x(HvFT)eoRWH=+3>V6?9^r*NyG}$MaYuj#a z^O6Nu|KBE(Q&qbrk}E`VPaF=$19lSQ*OvkvDEE0v*;jYL-P$yT7HawR$+~xx6nZ(4 z5op0l`j4jc(&nWL?(nA4)77LV(z$0X96tmnsqhdg_317j*!unVW_1_b7sUC?Jx$f) z1BbqHkDVQk_p87~fj+VFvEh507c00>Q?VK9{w89x1IIG!7l6`vbs?)6qqCWj&)Vpl zg8D83O-xy`)a_uj_Da6R+X{e;QdlwAVO-c%jd+mEZeXdj{pPBWzD#&NM?Yzp0{iMW zJuYZ6`q1th02yH^LF~b(hjOd2n^RAAOVzDNY;nn3=v0Ul6)JbGR#@gt)#&@iqG*Zd zQsPCB=(olKoJ^om?|f2?_ER|v_dt?=rk17d_iS-lvFKV|E~mM#3lpus2ol)SgcTQpQ!dIYRZk#oCixlu()+A0 zr9cEwph%9IbROzd1$+w6p=6$Cv;|SX>slz`MfBiUcCa^}-$B{Bn9<76rfu|oO-ghL z1$FcZnq>3EF=(lL!x8yH=s!yxLFFWoi>1=y?{I+9S-qQbKK(VJP^z==b-<7fcqz`p z6?hJIh7sGkN|d^*DtEB#FF=VH_(u!BHYX-JRBz!W;`xa6K94p=Q!n( zkbBhQ8V{LCm_aoWDxp#uOsw4rgK#3||9*egUi<7*J-`3!JFnVj?ays})@R*5>$<~2 zQY2f*_Q)v)ob8^CPpfI0y+oP-X!Mu`&Poezx>hlsJ?)cv5Nbv zOZLW=%O0g{RUXs{n1=XqF&zpDkGqP1L2 zIxaXHlTIkjHz^R@Gag(@*$8LUH-)2mC!uR8qQXPgr3^Nt?cJ`VO~ zcq?M(?|hoi5wU?Hc+%8pfpX9TFr8g@y4lqlt_-GAob1xB&nM*NC27gowI7gRF(NW9 z5?AHzEqh2;BsE+BYXy*9I|tZ9-NI;c{{@P>PQ=k8%nE!;ar1=c<&Jr!lc&5M+z>eSUuLWS%M7(Q(9RZjW6B_WJ;E3_QIMHV-d3bqn zsIEZI&CySm#>DFiVjj_7gW;Fshcw+n52-X8Qv|GiHZN5+IrSa+ z?@8vrT=+T9r2UvB34TzciTCi^OZxFJ@&8KxO?FcH>+rF8KaZ}O{J+Uf zKMRF@hll@n^52upzewU|R8IbDeokbz0Wjt^iTlVrDVh1P0}_8_f|(@>L&S0vc6i5q zk?7zoU7>52%UJc`3X9KWfed{YDn)6pAhv+A{?~Gv{ZPc8LzmbwE*WdXp~#kl3}Wmo z=#Ls3X0L8V=^@~fb}1q=5$4gCuPRV$;@ME#=EfY^BFhfXiqbU)N-~swATOHzu%Z`0 zV&mflgri6tBwEo&lg&5FK> zXLZIvEQQq`hv31fgPo93aaOcgZ-fZIB>O7jmYO)00_xdNR(*T})55hN^bY@0cTT zw~4E53#6WU^t#NKfGkqHS+IJd`VqKYa*noj*=d}daR#oN%AG-B5v9NNtqcmKT@}C+ z0AMgA)7>&4R`&IOx4>RJk(*J552j}e7;)hmo_e6#1SE$>sH!S z%<+tv2XjpqSfIPWWM_Cj2!ba{sn-4XS!7EUHrI6(*blp8GN32M|G0}(fB-)-{~RGFS~@~uY){N#m~>f zFV0jK!9j6ewduCulcF;3qdr39B&pII@Wq6qpXT7J!>B$Q46XPHrC=X2-0v`s2V-oK zUMGpcS<5LOSutX5adQV2l|mHZ@>oTFbw*<#olZT$M4Pd8JP?D?a6CL%e<2@w# z3cFz8_Gk-Y0~7>E>db7`$C6-1o?@=JEbSij5W?ZPpMn-~Q|*c(oM>1K7G}jd{MrLi zwN0^jm~=dtYf8~z`GmJrCc#bg;PT7x5l6=BGx2(+uF%w0o(yS5@*|Yo$-_OktOM$> zX93|lATg)ufsBVKBE@x{7T{rc&B4B$`K&Ik^9*ob25+zz;h^`cSFrq#R1!GY1Br%#2Sf^PXfj-9{x9%AnDH6z9iAlQtgYsP8cM=tVb}-$pIMlIpTRqCOkLE z^k?WTpJP(}JkdOYYwS6utS=4kr)sGQF)xxX{#8QE#T1hr>VO5DGb`BaGVdB4+4p5@fhV<5$7D4!%}{O1u1e6#Hxf2^Xa!KO0SSW&^f^Ff zv=uxlS?MiQI%0&FMsz0AKQo!~3sPQYD3Lq?OaLI+u0zNx!{e1m8VlidG=ZB$UIt|! z<&h(RECFy8-l?ww-MfQoC)JIw$i5wLV<7>2AOKHw7wBt*j?2f^p;3wWzovkPJpu&4 zbGG=9L?V8HmIA7mfV$S~rJv4~e@DSxlyi;{$Yh6hJQSgY6lNB0tg0M%y%N7Pi4S1J zXG(C4)Ru?37giDk_}g}EyP>d4Ff~#pEJqd3-K7^jJ2w|10Ot#8xOJA-qrySMezZ%^2a7b=8H6MX zUpor?Y@3q@$&J@ZjK`UcI*fELg3d&oQif?3onsw{yGL+(209$XZY5)y!-*|r3{I2x z1y-dJ=*~n>A~Q3mbY$@4jE!ZJd2F)A>e5jwAMMlME@Tn}3MS@gBW!~-efc#qax$`xQI0-cOFfmCgT zN)~dt+bnskbUBb1n916vJCi+xY@4Vc$6AWqEZlZlZZcR(umco^7sNIoLiI)1oY0lUO>280S?Y+XE0Utx3yUVfE;Jes*70{2qH>4u zy10s&TN8QmUt)PvF0Z4w>mbe)0e8ix4hE0SFmyMNZk&g%SJ^m<84;7Ik$b9P%Fi%90nF9OFo5BdkWoD zck`C4G`Lmr8FKTYvubBdyEll+Mn^tV9gF#VOeQ3^D+;uLL`pWJuHZADmvDHxg!0lbR1;ZPUm0z~ z=}UAB&h+CksF-M7hhVR z=k2U5GqHq)kAWdO{i-(-hc~xJ%Tn{tfze8|Ro;;Fi%KZSM$#%m|NI1GMOct(sCIh3 z21&)6M1BdR<9jq$muSRWM64DB8tay_24=)-Qqgs(d4~i`DAw^$Fr48gKCU*Ky|kH% z@dj}t`zn8R#&%4#;KYLIsirb<5c(8;lbP0lDN?-H)54^3tb>6$#1t>~49xSu8yrA5 z=rL$~gyt`YOM#amc#%!ivlDA7e)TOCy4mHhK;%~in`qn*h>|&^v&GDrDpOSBx*D4Q zS|7e6d+>-OQnE;fRhlC05ELkIeS$aX%x#d&{e-p)AX0o53)dx^mB}-pKy|Su`HUpR zLeg7!1Tch(`U8FoW$omEQ`Q7?EHHAcki$S$A)IdV1@ZMAyr61qp}5~RvN&PYZLd0~ zFRRpi4O6lHkG4^qV{e8$+(G<907a-fPC{5-5tJ$s_W4%lCJZR3ZOxn1EY?oGNFcd=(O({RKqFeAdmdOAY z4$!NJ0Ka;kiBWanj-7zX`SKp1yH?YIFhN%-bc;xr75IfodH!RgpH-4aAfm}J?efIum(JIhp2k*m9}_mIOjrqG<;>@~cS%9$g8%FRv1mGT5DZK)C7yz>+YUO-@{534cT=c@x>kC<8OHVgC2**_iikR#bu{3Gv zD@9!`B0LkIew9yCI=w|(D%IH|Q2?#9M3zl;T7H5$o7DD)Ou|G-f&jJvfC`Al4y6#q zmrEC!>Jm(bM#U7f znu_HfX#)<^i0b0GCZSy^@KWK|Es_Av20%JvCl}5#CA%BR2b0`sFNTzH7G7OOlX8Ae zSF;`@Io!W2`71CVU@aT8RIBPev6t>^_`x50>jz+w{Y;h1Sm?)7_E?l46n;;K z&O#QcLSbq-cu!d$%Hc)A)rmc20;>Y7Wkc{h)+1e)bj0$>qiICWEYL#fHkyH3W_vlZ+l^vf%zQ!T=Ki}m=s8`J5O z_fr^GKIxrmF~X`k71<)i*F(o!AML#j2|Da=6g)v(Jx`|lIUE(( znS_nQp{TMW^dn$-h{Bko_jyzjIB)= zqDz_dxkr&DOAp2TFr1UpPCBJH)~i}pbGLOa6p3Z6m0#G;*YX-6bSek+cDZ_JuKa2t zGsSKiqn?SVL-oDq$-czI7!!TCj4_S%F<8L-r$^0`$_CN^rL>HbLqXCMcxdneGM#|k zKS0SXhHeJw;%gE~_G?+aJ+iJN&1Me`Wl1S|G)dNtq?w~Y&3BB2XZzgz#fb%0Id+8fzMoQxR)qJ;-;4BcpM=pTCcAN)n_NzYtLVgaE zm+vXSF~RL*=t6)~{3n$4qnS!*6^EvhH2YR3Xi|6&1ol7v$g;EtJ}L5=Luh=(EmJD+ zUF2Bn;TTtjPyc1A-w_dizauBc%k5*avDIa_q3{MCz(7pMQ^lgjOz_+~D2}yM@2ayf@-!1liKOj9*p97qL+AQuW&3m`1ur^+$wji}$cwMhg^* zx2@>LYl}V zU3*pTNoCHl$)Wc0Ygqhr1J6w*aerVAY!)1;)}4jjTs_bmV`^emXQX}Uxz5x?3VJj9 zUI>?|3GUH>O?fd0%H5+V0U{4yaMu&i7OAIb9brOFI?|F)jAtrw3Pe-okZQ1|!u~fy zb*oV6T6GvnazG;X4*ZQFmp|A_O%@V2x(=k;{WdbK9y6CZuAv?&9f^M*_>6RzJRozZ z7{zw*kmQnNsgS^^W(Sj2;&9@siDM&^jO#?)4C3_J6x1ut)R~BLiQu4JW=S;S2qFrJ z;MvEuzTR)8xJ*Y9*NwQzf}6UMIFui4u%n1h1^TvnRzhYyh65UxPu#a}5y#^%#9{VI zdHhWDSq|)opb#7J24b^2{q1!VAvz#D` z7znU~4vaDdM@3Bi`VYc(MGO9B_EY`dV9f$CMh&zk$5(jEb6BzC1;qiZz`$g=)#Gw` zF9t~p9EO5qa8Dy=dR>-FK~|8u7o`(r_m5WL#LUhMnV7H$i>}q+8w4 zli}M(n4^Pl@djDn1Qv6dfDgxg83x6jbvD+Jyi&iO;7AqZ0#|Bm8S>g~8r}7_wHX^s zCh9%$#&91~_871mb>|tuf*Ixt7G+A$H#%)3UwdFh-Lf_{l;7furFrz`M7zBkt4khh z9B0G}ax0M98nMR?I4bi6nO^|jDAtT3CYBP+V=kv?WL4@t=GvA!$a@_qv~t++iB(YC z*a9^Q<$Z~_qK%Cy_@DsBU|6oukvEZY>wY(K9HG&OT}0Fg0;LpNRng@e@f`lyONdL9 zsV2W;3qjrsq_(2{BXdOZx@dYG+mY(SnK3CFH-1%p_-2Hxm)^&%MedpztFyD47d}pP zI})EdeI3TMy73o-@1q9Y5ebgMax14U>pbXYXA?@745k&ppKwu-V_VSntC2=a!F&&l zXt@_Ii%d}0;n>Oay4E3;_WKrDfamQ;Fza6UGnG6(EI~--rGtVKMTOf3S;E zV&6Sv#T5r&1$`QL?dya-n-j@tUg!qt*|= z%eM(64QC+@Mr%3j{RYrFqs4@OqVtv{36e*xwFzxF4~Y#3*6aLy$COWarHrhFa)}rD zB==e1#-L9B5a$3p*kMQ@u!gXo*Zy%Ng(4W*mx(WkA4~1WBZia)Tm@CgDP{vb15m%} zvk7q)$764!g$b!le&dWj1CESg2&&o=TN00b?-s5DlvsdP28HVXt%RI}Uc2uAB?P(} zP(LnN{eLNO2eDKF32T{&gJMuhg4v><1ap+nKy%fvU=V1Y+HHdQxYbmk*6T%B{$C7{ zAi+y_zrr0)n!cx62_iSGLV(TH@C_Yee24f_L!7Q6MtG*W-2}7MzukDS4{3wmG~5%seCs#(8a`Ai*U=yOz#3FfK{6UXFs~7bP_nK|}*fG#B^^pmVQ16;xk*d)_l#J1Sg{x+qn8)A* zEnd*dF;QrDkdCqH0>d|6`ArbtC^f-}>SP2lTc)WmH1P3if(iQ7KTL3<8exKy)gTj` zs*Xj_IrPR#8n-IWfWT1QG*tM|z8utNID8n={)Ta6dP58D5B*5e=%uJ5#b}3OX1dx0 z5?>+xpi2UeivP1Q_1}osh?!A_>T=n{gfD@>9aiSYFE;ep5fCHx6 zA%qKzcNePb?gZiDf)PH~h419@D$m-ZK+R4H7R~3_m;FW&uA{4E6HC`jcSv%;@YY|^ zybe?^Y++-AzCoitXPTxFg#;}C4%0#j#x2C21}wV3NJ+EI`Q;(&aNL4Db`C#gia?RC zW(y)*gK3$q@>^W9O@4hfU+7=0U}<*ED!d~#m){Y~GU4%@NrY6bK1QO2y!8+{A_oGS z_F}2xEpp)k+)Y#AeAnTHw-@5aag!U|pw|%fjp-SU(9(!&W@7HAxb<3`m-wo>0@xs< zJ!mlForf9k`#IxX|5dw`1|vWY_)VmMj}8`4-Foree7^*AU;;YC z2||@&5`=y@qsQWaUcQm_e{9VNVDJfEUHv;U<|`31s=t%8Bz!LM|Im1pQBBfP+!$LP zDDe5FAp-&*V8mCm3PNj7Lp1O%cEi!CY0#<|1L5|{4S=9UC_=@-^li()z(z7Qc^F>? zqvWe_gXKLS>4Evxzt^F(G>e293IcMygRG4UI55ZOtHVSy1bU^V3eE#9j7~v7?sbs01sa@>ADwX1eDtJMy8XoFqqlmR*5RzUleE1kordsO62_ZJ zn2)arNJ%|Au$}r1@#t3re@Z8unm~nI{z$@SH$cB4yh1gq$H0z|!VNK^?>rl(gI!1fZ4H_9Bxa19F|T+DJ_k;3;qioqsNdCXswXX}|2nnLMm=z@ z+JtLZub{+y#OXhKf*LcNKF*SqhOtwI*H>Wav8C*Bb%%IMjj@%kFzta%CnvwSUR~5% z26O`W5CAj3k#nju)Dz6xz{pTL&F7n`j1Tnt7hQbzzFb<@vK12a9xNC{Sr?wDL zt~&^o7KOD4`eLpN?NuWx`{QZ>jKYy(W0AbxZeI2M^N*|R05F2DleCLqcuBAiS|q7c zteos^>e56=p@-*s@~9Y5`A?WR>Y)mLg#dmG^^1%8l)Ln?J%@uHTpMTYox5=Vp>?l(%Iq`D5> zn};YwqJR*=t2RUrgUE=fBE=X`cr1L!NXNp0915gk;en`ZZnZI-ZWWoA2nTU zvjfRj_p&|m0ix~#9b`&>^%3ewjqU>?CGVxAxZws*czp_XelPQ@C)jm4$0ma528`H5?_({+cdYLdz9%T?cO_X{D;>3TU3b^h;+o`1 zl57Tvwzx>oHPQw7E|6M!>~W*v)8u+o1Zxci5COnwxM75&plG!y+&3YsK> zP{{U6H5QYJqPuXm$x!keH+El8dK8^*A`#?~ZX~e>6XhaOvZ`7-(5`3|jLR#BfdBpu z>Z&u@W}}E~Hfei_5xoN(U4vR|-_SX`9J;91up9@TdDw8!8lB${?5pxsf3&^-$Mpt1 z9p#Qg*(|3AkBPmh8)ODwF?G4>6fq@X&q_u(8z*pjj_WAt!CtXD^wct1s=O97pai!L z9%o;TM0je_2rY=1i-6IxVy|!+$Hz@WsaR()uviEO~i1oDIfU3|*~ z!@|>9ZFx$_JB5~C-KKtDD(hhfHsrVk(XUeBLvo@H7YaKQeoSoZ;E6VBA&NL#FuuKw zHbeo!ni zT_TMy(X5K_8v?;!5?~2;LWfcE;+@Fc`yh23~&$(23Gm2WNL&UOo;C#sEvSdnd)W? z1GeD*cKoM@(8Lh|*Cj}edr~)(`U@!+J)fWWA|US%DBtYk$s_04!ZBF%3>7q4k71OBVv* z6|JZaGVdNb$!Sal^CU1*93HPOew@zOa&g8GgpYD3g_VjhEKV$LDZ{@ds`c?)8d!vG z)>+<=6$*40nyH#hql76tb~g4?mJik65=7@so8K{n?DNHh`m{on9PP+Kd*L9x-2@1~ zH+^OW7PuB+tD*+e8RVY$4i(D;tTcE9z)(HB1iuvnooIeUG&oVDDee=-G%I`?Nh%C; zO7VTMaxRu!Q!(9Pt1)cEP2*C@*%hd!S_i_$bDgBH0(-n9H8q0|OwH4X!XAZTu%w18 zN8os9c~%8yboiPT5EBgqNlV#%j!_E+fWfig3zYB|MvJ-zORjx5)X6nL?g3KgnqAD6 z#@Q93qANK`8U{bAXBe7RoQSeqT@nuMYlHbXe%{l56}(C7AOd{_P`~O{%Z4c&dj};R zb?p_rMv7|?S|*`Y2t6vHI)v_%(0d5oB_U3_&XLf1glagZ|H5Dog5rYnX&=^_=|Xs88_g*`A`+NDuapE!CBc!NsPUn@m|faw?htps@L7aX1y)z-mr_8fwwP2$`2cr%vz`2;7X zarTuaCbaul@3bm6!C12FjyE)`CH8O;gVv~7uPwF?{?k52VBET0HcW2&jH}CzW3|LO zB>v%=5P0`8Wv)cZ1p621WO5whB_KA^CP|m7H^m*};5#J=TL@w3KbmRYpojB(`w>X> zSnx=buJi3EFj5Hi+C8+K(c_afQJdaPTXV_B|lwewFe?>`<|K&3->C z@Bnc)3NBwY!AX;Gl*TP0?tHU)pPDuK3&FTB7FOe$08-+fXV-nef%^h^iu`7Bdw@`38=w%cO%xRvAE7el! z^|_*XxF)`m8qE=nB2ys_O35KMR}>`qb>zkzXQCuVs)8WaDpqk+VYK7|j?5@i%bucT zZ$ZD%}m6!pM95?1kvrxZD=W1fDj@cIhHjIi7H? zC!B|{qrs7hV7^e)`352nnJT7}>DHxSIZMHEWCUM!tW*OeIk3M)aKU+vq;61)hvH!>h4*RSGVGR$Iy@1RS#K*Eg@rrrE%Gs4C& zF&bu895nDMRwP`3J%s;@aJT{wdJyulhVej{X$t|I0sy)VnOJzEpL82p0m1YKhAnK> zUc_B3Pxc>oLcV!J`_s(me*2wLkw23WEiDP>zYm=M_m)F1hZD3vk@kJiw#>{?%aUNT=JwKN-gv z5`Tf3{Tke(s%CHjiWD(~K@U5L{Fc}F#$DO($emsLU&5&ae*I544zK-Pu^Iu@xlp6b$2HIG1Q zB%XBfK{WJ%1k`ZB>Ri9IClV#2SF!BIedAc{g*xjCZih()UNP9MZMKc`*!gOso zv~GTt2V%!cpJD{Lv2mU@s@Jsr6Q;cqWfNU+#{;BnLdWMwSslnk|DmRQfgvS6qlj#M z4M^!!)Mx_J@HIrAdYnM67pmhmFcrXR0@*&RBQ=ohHxkGNHkF})=>T3rAXf!d^EQ#0 z0pNH5u}YElB3$5?@t|{%gZ$<$)*L7mJX(E@KIZ>8tE9JHeffgBRR)ELb1;hmL69|e zfeB(*XM)-4RujxoGfgm8{mTUN)cGcuul|W(@@}9)gUnMWm|(j4{dp(SOtr@Zv(;B7 zn4>;3!Cdu$3FhM)k*;`N+_B#uEC`NM3kpOSM(?t5l8uD@4N9uB2N$z28Znm$Oxfxw z7VOS%8M+F~Qi`9ca2+s5Zc*?IH9T4Fy=1RGgj^0s#RYbzZrmNy;yXV zkSwDFlQ&oPTNsS^RCIwu^+y2ndSb7%cvNi#b0i!;(Z7!R_j2@?IT|{k2fLuKL1y)& z`0)4PLq5Z}KS9r(g43%QX_w+i?0#&{fJ=$fJ$}p%4c`E=r6hZvWcAjHHj_E>=H%ir z05{_p34)lDskie6p~2nz`^Ij>)1AG?>&_-=BP=CG7`nyc#o-B zkDdyXhw?GO8tRY_9k6(R+tJ9S4f^y8o4X~TgYqL7UGZMDmlPG%Knw-sbq-#EjD6*J z-ZSwIXJ2rmoLIF_K8SC)cbJ_B%Ywdelykv!s!=H?+>JF(78gto`P68>(fF9{oQCGU zwn4(qk^#T?<%6$=X{tc3c%k{KM?Mw~IukJ`9nRL~z(7HCR9QgiWr0%c-jQp-fv)Y1 zq$AZCNHwk**y*bjhZZ^@}A zxSDHx6_Mh|8eegw`0h2n@sZ-_8s8Wv70`128eeLxmHdKw0d~toitmx}`B8Zf%fS(na1YfL!-ilmYx3+37$|6s0;XczyB#ak5+b2Qo zt8_E$?kKAHbf$e62Zj|)#LbG>r1CLRZAo+cBon=;Z%V$8cHI&j)S$*iI_nR zTrR*!6@N+os=TY$QLt-Sv9Q;HM^A9_eS{cgG1imm=%6yD5WO z0W1Lkds9uk0-G1HbCqA{(S1B2o-!dl8X-2`#fK_1547Fdhl0te7qW9x`r40~ptyCid zPV;bVFb}6dKh~JmY7GMeF)#8a19?~tcol(I&tMLy{-dc5Q;#!{6YQXv^k62wW`4Iu zrK>6goMvp0*S3zDmn@?y?bSt^K3h%Ffp%)V4*1mR2smEHz&qLQm*gk5Hl~H@GjWuE zUe!#Pq*_14j@F7v`Bj^&``-zDol^gGTIih|X^|q4QV?=<$lq#il=MhThqOrg*hqx4 zIV6%<9iPsbjbDZ8Q?ck3iIh87X-ItVLeSAyT@4^+7qxq&?qI&N@LqD^uSDflrXI6}d>9>D_m zeXlDx!x22h6>N<2KXe{#MBh!(wUA_V7Qo_!=uAiS)~bX#j7blvwcW)rN0g#3@`x6| zsjg^aR;&s%nI;lpjJku_BA7@Oe;N07=e-fX&MaJ2lZ0i} z%b`n=*y#F2s0>%juqHOI>T;egz4E4)(jsy1%YOY**;R8xOV#MLv5))JiYyHV|NR%t{_|={ri#8_jC0ANQ9CK+M%IHnc8-wT&U9iv z8lH+Hotn0ZTzi`nl~@3u1E4oB6=M3AMb|W2!hNdY{)F5sJlq0!5CAq?DVd%QS3WaT zA#zQJdjXQGI|r+ht9rpKr@>fuo7-R{$1aWLyGJ;>%U6Yld14p9QBLe=G|?N%aCNdP z4|7g5-6x%q6D3P@Ej39K;a3>p+nBU3uqD*AZUT4<0No7ivgxMJQ)nO85<-=v^ z2*<`6NsAbhBZ*%y(~YoS&5^K{R4QRDiC-|&)!475BAmzvw8fnC!s_p48DjOu_&f`v z13MdJNvppC%>vY~dOWQ2=541JskFgSoxw6BRjfS)yn!uF2Uju9Xt-5ON>YAjrX9XYUD(u# z!(K=FRT@yqNt$3-k0R?@z5P=PgaDoefK%j?4vO;#!zRX!L!IoXB8 zlYmR)~dseYJ?Qnkowt@RP!DRN11koE@`^fIHwU~=u&n?EHv0{9RBYQO9OkM>eS zMi@pp{qVAfQ2_S|V~(0}5M!EQ9LgAP@-PbE0%6QmCmzK3eh0^1Cz5fLhfx6C0q|BW z0S*Gtug+L_p!Tzktdl6~7nR5~0el7kWVuyKfV%+ntH19*P}T`X)-cLi>X9XYyC_Sl z)-r@VIXRrH_Zj$q*9ARDVK6Jxo^3iQp~- zJspIM6WK@L+MBt~K>Bv{p??UVqv9Gr1QmlYnz?p%r>eF`6|O5W_XlplwnlXd zJXur}f@{z@=*ez>U^{W|TEtnEoH^Im(+D`zu*{5A>Heg3aHd`yEXu=XpINvUnRnR; z@fRWkn_jN7C&4xnMI4sR)Hf@%4qk5$0vt;Sn5V}@L(uvt&eb_!VmnLfL*bR#37pMx#!0QT=rYod$%MZCp~K%CqoO z$YJm7tbnYUe9GEYoLL{wH0sI*lyB+E9heZoaAb@dw_x7HT2?4NryN`UGDGnS&jr{H zo~ij1cfZHfE?r*xrf71i#vWr~MUi zPm*}N6@47Pv4XyL>=J zKctM&mH$xj75NpyhJO{pc82h$kv}USOG)2g7CN!fs=hHTqYi|!pWAT0OHQtm@N?5B zjsJq-o#h}bFd?G@^FX0iLTy(P$UaU(3s{nk6`R!vO=(kat^5ifTGO|5mL7|o&6s~+ zR2vx8G)AQ^!ZU_dD~aGvMldBQf>7OLqu^F@9VcA9@${6?I=`XWNt#wdlb)c_;)8?K zUs8me{bo4&U&hY@und2WNMpUIEX`%4$&L)31of*GcygU>pGXx6p zL1nOg3DSoWq>d?4)X$<+$m#{iC_oAcDJpE#kp6&h?KC!^koBef<%(T^v?Cf!{QW)BWm!;w911;l32%<|U3Q&lG<38F%ct&_^v`LqT% z3bDO6HW1)f1O_ejAWY?m3$O`L>w%Cf=4!T}_p2QU7%KOeoI^qJ4FFBc;}@B+{-Jnp z>@)8YvqJIiRyYb)E6P>_%e#EBS;0f`KIJ!6+{n$qJ<9tt>-R?hj$IpyAB*=@L==>t zTQLy`?f{QX3dMVskEs|@1PqAl)tLJd8OvMZ}V?(LDxce(6szEJ(u^5^i3NpK21zu;ngS)>% zCgZOb1hzZKioSRbcV4AE2dQQ5{)!1|>)({?vM-`e{S$KC2p=ROR}eT|1dU}t^AMqb z!;^%s!Zl`YAdu+t4jJ9qDk#ypQlBROTjbYQe`u-C5W4ITQr`)9+#fd)=cwFdsV|eC z6WvKtUmglZx{yit7bBf8aLcr{ZodRAJN& zb(&Nasl{}6Yt~;SpXCbe>xKqIJ|F)D)*Z0&V_e*-x>;Aiq`V`E*Op+bKT9T303LUz6JIl$N+OM zR-6$|2d=s(FQqtcUxIg-&!G1aJsxPxue1y;dInDQ4s^x#$r7&?{|9M$gN9>YJq>>@CZXIsixFQ@!dv1B@fr0hDpjO9r@B15?TVkOBUx zfolk?GQdl<%-#h6&NRRo0NOX;VXVtDw)PKLG0xAhChqkI9%nk2r0C&cJxmk9CVB^K3m8SFHKk88GMaG> zoamHEa3R2n;?TwiwVdK7XjuUnm))nqd>c)mnP75m1=OP2P}I*@D$to;cCv{>5L-<)Id~W; z-3V9+2B$)e4RH6f!*><<3}FuvUPC>Ka+3zfg189?EbvOL9}KS8@c}y_r<+HPT+MO} z$dP9b!?8fyx_Qz`lPS%Vgi==YSn(_9PqS1t=U5|^V+8XlS0d{uao z6&J+Y9@Sp5q7)XYZKqito3TQhW4UhDMP9&{7 zJTj%o)r|yCTk_EBH>r_Xx^MNef+ONyG%E%z({#MIBO#*UcZiU7O$yvwK$>MsCprncG=o_2(30TGzy$u-j{89Xy;N}XKg(FXMN>z@Gw zrV^n^4#x%Yj8benq`MI7CIcfx6{;)3^#X?bMymS()+=ONF7~))Vq6tTM+2+}SomBy z7c(d;9kXsd)l+!YZC@!|oE+5~BI)Af@J2W}j~$BVfbt4;voK-?DRY)qCUX{Ml<>u} zqOu|gtdFNb6+~FSFO3cwuKC?pl>DI&=wbA%rk*_@5i6it1NX|djg9?zB$Zc{LIgf# z>it$oA6G(z628L1f?w_A^1}bN(qJilUMnpi@6+J=pH>QsNY_fU@anZvDn!ysa&I1X z(iiA5NdvA%RZE=91j3mYQP>vaB2xIRKhBnrgHw)%14p+Lh+8}eG!Qhs3=@CEI)Zjm zcOeAZ>+%7-DIWt_KC;zt6r)hxOi%gvkSTu-T;7!Pu=&Fx2_kf{2;-Fr4#fwuTx6>p zh;m)uS_>J(oy9fJ(?Qn@vfom4Kk%We+}j4lf9XD_nhWM=V5FM!W>VB5=*0b z`03%x9*VGK5dw!Qxk+2<;P(V?60p7xSc88g_zeMP<9H?dRJ#H*8xR`)7lc~Ti}B=1 zl>frjv!~*vkV8=`{2}}^D|#QgYGPx=jwF`tuoeCrx&xburx{SZk8U1EHbKn+g;MR| zis0CnXF%~6bvXyRI0K6Bky5HIHh?Ihm6{3%$X;KB7&!vA!eempi52~`Fa0lt zMIB6OKzat%G4-Vtl(m1sDuW|GLit@Fza}3|8#cbgTk!4MOj11!D*IYU55+IG!VOGE zl&65u{_GIRaJouSgX1`e+Xg!X(^XIO#5JSg(DNRJcu_5b)ra$W+aC%dG4{%#}3Oly&v?|6;O(_jH`Z_z0AEazXA*yM5jTe&f8U}UCKj775s9`eFW{h2t9qC%+ zZ4fEBbQ~HisMJ!@6x(K>JrV_rXK}6Y2n4Mtr^S^8v+l)J}}S+EPszH1jC@zo>bJ4qf9IMk5Lc_W0hm&zY}(mP`}DbasFv5%q&4qe*Q8 zo&EK2Bx0E);`v@oL>bCAb1cIOuL91BuE5h2r3^I{abe*fWz}9v)>njeI$8oNx+)LS zPXR%~x`)F7(pTnN=Y zr9oX2g#a@p3OM>c^(IB1K+z9Ebm6CBjRm4*9OYfK`~W_TN5pE%UA@z23FrMLW+-Eq zwkJxFJ6SEqh_)lFaJwEfZ-2b1?Lff1ZidjP17unkA-;6Oi=8c;g;scfe{vS4fb&Vs z=@k2Xx7dFP3-i33aDRh|QOO@EPZ=iJ@)hL6L}#}4>N!|I*M$B|`y(gOtQT3~yAZIV zm3T_ZH?ngwqUS=ieFIR1tHnwe3GHM&RqI0}Y6{3X&Fm<4IUT{FU2R%ntS_7}wcIr%s%oxlnf^6L+c=Zp>zs zryoae&9%QelRko4O|NmGP)@bNAq1@GEIh>w^iVxXd62Y0AZ4}Axs0g4O4Z45B{MT8 zqFnMUuw#Ua$vKdm>%<60Nj$|pVTAYK4;;z}KID%_LKjFlgc0`B2!nRe2(N1+G{GX; z2uz^;2G$M>S*fh>GYDb{AI~6sP2I(0sL_buuiipR?I=*8_=Q$@hER4uffO^m3s2Ug z$~~mLOlWhg@O0^vmcu^~TJ8g;0nSAgwnqxlVOF@W2%Le^tZ(N+uQ^W$x07}bXw@_5 z$L)5)aJUuzH%P7MUL47TrX0`=5MJ<|2tLzRcf=t%+uEMgR^N%k0@Aq%^6xJaZMANq zbIJ1sz-Xdl1t|RGw^rN?gE=|%Fzl>bXZsCU4dy8CQn8hLR}2MrGdmOy3dPj&BXLC! zvf5Bw=TgLO3B`X0I!`0jTu4`|(0pqFu?vtoTuxQi6{Q>Fd{b+CQpXFRBd!s^Gj@WI zwK!yB4VipXc8HLjK(e+@Ece2mF?^9_F!k>M{|5mpx)e{>`fcF@w3N~M!9FT=C$u`2 zok~Pla;@+!!cvMSyOd5=_zH}gttc%!_1d@krk;N!{Il*6k`tjW|pwIBd~OPi(H3&d8QhUf?C*&>fu*vFc;gE&D`~S!9KKh|Df{vRZY9A1#1vJXx(6 zk($Y&T-kQ%JJc`8OH~aS>JAF}9-U_>euNd?CcWrpJYBwFUcT?icMkc^BHwEuEW8(L zS>cs3;0fn>IR8d}>&CdAoJWu|mz=kflinwq0Eu&&6Q_CsT#irDNBxbgo>z?aq?t|S zc6Ay`u`6-_MXmvbIO!$>=F(s{enx|d)0cycBEL`F!`K(HxcxN%v2T*t_wgCcLYwf@;0;dpGPg95-nM?t>~kiL5KmB=-6en0@Enf3(6flT6u!f z1C*|=z*8Gy9&NA>o?syhx)p8`r|?TWRU}EeIE6Bawhl_WZpTL`5{GaKpJQD6H!~&T z6fT58bdvKJ;atcM#k*MHGKp>mo?`MylX2DndNEkN(fELUm^S}%J%hzr>* zqW+*4w4$rqIoz`yZp-1mpWNrT+z*kvJ-9>h%dIdzjL=en`v;sVaiQ>TSD&Cpd2-|} zrelbtgVIptzJux1R0vh);bFhkkMjOyg`Y#fiaw2}q~vFKM$+HtotbFZWrwCICGS!0 z_D^6RPhOCu+?PBVxM^w3a|0D>?#!SbOZevBF=XKwvjd#g{ULb#ys4 z(xF%D!J83yO(`6jIZy^gl_ng>4&V_yV!47kLr`=p)b}u(x*aHfYV{fX&cm@EXD0Vk z>YEAGJl({cZ=7yIkiTy_&<*;WJevWQE^t&CT3PKM$=6rk0D>#fWt-K7Fr?$HTyAK# zk@*3`JhJRKgZP4o*$L)1peVi}pAgYaZAL;+Es!Q$HHNufzd8#LU4-sO{@QIYwkzb+ zjuqYum)(l~fG1|F*dt&9E1RIDsQs=1N5O+tSL$M=mZMf;`lwXZ!ya1daZ;nVtNRV= z83(mpSsFzHzba*Gk3>_3+Uk_=mjRBk{|iWgeG;!)s*UE#z7VQ~;`vtiP59wfbj^Op zJz9XSRBdKzP7#U{E8JVs(j8C9+8OL@5v@-&*sHfV{)9x>ZG_`2D|~Dh$~*xDNH_`| zj*q0a?$wRZ+vNDX549LoKER6dVltt&9O}m%>MB;Z1)x@iRBMT_jI_cF5U`@vcnaGV zc!5;wDu=C-Z0D1$71^#4w#zX8D{K=D+Y{o_!htKpo;6M(`S{hL?NA+V0Ue~_4W;8z z$dhId2Yu_z9?CaHM{i)vtOiL$?Y?t}j>Ix!N4$G^5)BIodMp1bUkyzn%2wKs1 z@w6N82*uB_!n;u#ad#G02Yl)Uv2$}E3~DuxX?a4(CR*XU5in$TIAqeoUrMrDglv)( zz7hc|dI_Fd;ssubCxO&d$Ntpx=8su}@^mg8K|zB=(5+VZXc06P<2$rLrp*~hrU01G z{^Mz zse8EWMyU>HIo0t1Db^6}?v@U4hRA7h?W0UBj6>!+BSsCCwrVh-vEyLbFQuzjsv5P5 zU2cfAD^vX@m5g09w);!^p>5&IqJG+8Oi?EQM7PTzAt}?ZRQiAd1_Z~cr%)83bYgBv z=A*t6Z$YWU5seChB-S|?P<=mQLd?Wfsv0YKv|as(CP|IfWm--3XePDzfn!-_W*QVblC2isLAuZZ`N5LByLuJT|*=nZMsb15?8+=4;N z_S)?LuarfY4xvBz)wF9^w&Ls2GH{v6UUm#3e@P;L1G9Qov>8vthtYww0h@QiSe+4J zavcA~qyd*3I!d0sM53Qjg1GANZ8GI^^aqkMbj;UIEiR`jQ=p379a@Cqv#jtdZD_Zi zZJieATnLuLr<8SrSW`c4BjZ>wI!kq5e~2uX^(w^!ORz-q8 zKY%dgkn*F@ByEHi^md}vtzae1m7q~+NUk01Nxf%V;qwr%qG#h7Yl{OQ<-4)OfETyq zEQ2qFI5BCJG)|~y+!Yiqoj=Do+p`0XY>_uW!C5w6m9`?6AsKY<4@FxgZ z(GT(DMqfY9bKEFdc$mbUJT1C_5w~(9_8$~+b%{z0XM}po`?U8Q6crVr2C0nvDv5l8 z6+TxY_cL-B;B5Fm2v(pBIgZUzxTuFPz(VRVo07!<6AseDWTOyHBB9y~wN)i6aRnas zx80fkE0KN#kbXSfSUDM{`;lNb)tlKio-F?rmOwe~8GBU7QAK0$OPnft)JD)mh32aA z&nwPw#eFR_(&BwYVJ#%QLI{Ia_#6bVuwn#0ln@w4Pi2o3y6NSgSkXR0<5(u*3dMah zl_+9r8O2&cel=WY=v6V%)!`yduKKf2(UUgaR0-LxBioj4w8ji8ycz*3`Zk_Y2(lB} zoI`Dv3*EJt-pfKheJC_aJW7SnB)X=^A#J75&a}dRz`3%b=j?afiW<xHAksk z?5U;*>2+9eN5F~};VGgcj_7|wv^_+KZnnbrA@?z{7e^nFs-6N#kQbVukGPnndmR9F zCTI))EA7)S1*HBSPf(YUx|OCLMCyl0y$#61S3zC=fffDncSp}0pkzEpHAhm-S4j66 z=&bM~2wKr0c#5J;aBl*f!Y6G9(%wPZTA`f`Kgx=}k8tdG=b+O?z*^DCc;b}CLqc_? zfQkufBWIY(zpdCP!taD|woaG>IU|^o)F=+x;WUanSR+QSMd}V}INReOo=jPNNty!C zs9Dg^EgGkb`0W&*75IiU`_~{fpFk^hG^mjz4j7u&fpIjG_FPvajkE7ocp-vTbUvO) z8n;$q{#!t^2+G%|yuQT(atdDCIp@cYX3^CB#Pj0w95QL=Zg2`mF(C&ZVrg@c=N%>?^-; zbc<8KhpS?+HGGWnIQXS41`R5)fKb5^$_?BvZ@XzR?99qE}ROK%13&I6fWO`?uJV>D2> zN@CxEV8txN{1#*0U2(B%pdsQFNo&=F20NHaFHo40dYMq&EYrwlF`DN07){hzP^lg) zFS%%8>{}V_+Y;>+G9H#Z>Fn6siaWJOm~%Dz^AVH;!V(z1@K z0J*t6BzB6&;&kIMjfI;f9Tm; z*PDh~`z{O>cnU~NHr%4w19ZRDJPMV0kPYauDC&5mKy3inK1q^sgB9+HfE7I&PcheY z?Z;&_LV(GSfsAIFM8jH&XgVSql&Bcp^bsflOC{e?kHK-J@u_GAq0s0W10} zo@hc(K#ak3-Gu(Y4rDR__5(uuZ}`6mRNTzl767K(GYDoe^ly>AH|ehw`WvkELa!;eQGhLFUNBQgA) z>cr5^#4ymra2aFB^TzPOJ4rDJ!S8iU$gg;+V;MsPF@)k-==K#;Fc2+2O3i+Bw!ti}`2-X!sQ@(&d%X;VK&YI#r8?jYg+{9A#vz_+IQ(V`Fq` z`y#dH0ZG2uP|w8H*2H!WW4js@&cxzR@EfK3Q7R6UeSc>fqn#DL9RVv^j;9!79q5vb z@!=M2j6B4`wsau{$DoRdauJG=B(M>AruNZ49VWuBvBJlQ@UD0U57VV7$U>I~Kp`iS zt#F!9{ME^c{tT_A`U0^)=q$D8Z5^#B-3YS6dBRsLMQ}EHKiIoOxUdt7T)ama-en3S zdWj4*!tfA+*p7;4Fiquy!4Pgii)Y^fI6gIkGwpDpF+NTQS-ScajxjBqPr2Dz?teh8 zIx>|LgeTPsj}p32)5QdWsIT+@P*4om-fPtNd}*q4+ij!1U=(gPQG@U zuaJDP!@*Z6e4im`MK|Dy?4Jxi`WbKNO2SVhOeDD;15_+zF9?)P3l4sy;n`5 z==NIl*C@{Re2T7u=<-LcDDTUI*c7T`X`(ktG#y0PzHEiR!GJv!$9JDPV!#EBKSy`R z0i7D?SAU=;26Hsmoow@^Hyl9RU%P4Vhu>iPbsHqA zp>NXkoQ8ZI^6bTcIjOl5K`Tlk#Lm><{BM&Jdy!fO=}zpjuC+&8frF+Ler9z27+vrb zwGP>=rckYZP%C-M%&#O&a|j=o^1z+b-JujZy|0P=bS2o2WYYRdn zp(QO^KBVFVdLH*7tnNlZiuIQSmFEkInDMiUbtJi;B-2Tf75IxW+<+Lgr}PZ++CH)) zjPV~3!S_bcinercYX5k2_`&^bWgZ8+U-?iL?HI6y?5eHsX9%MFiw$hZLoLLB`Fn#Q&)q;evbUl2>(LiKQ~PZdfq|&L&@Jk^S=WNsea_2PX1?w ze+)9!iq60j6=e%N(B$}keG7=gHUI78-vbi6FZrJq{+r>EYJMr07XpnE62%YGJOb>= z0+&!=t`<0m0w1QpZJ0|f{8$98mTA?u@f3mCTHr|jh#9k_o_TF_wnxV=ndzKiv+sli zY>c+Tr6TZJJdwiZP>Auf1V71oWqX7?2q7T4fV4i<0~pSivQbgF$V9szWEI{a+IAM< zhvDh^YGrUPSj&pY&h6G;kg)>_42rVp_D^b!LNv05m1_slTWT@j{R^SMR=%#oE2wb* z+%OC$L%RgSQc%d=dXfGr-WcaH)|+nhg!1vQLpe}XYG-&n2&^cJy_oeibgFEc4^L9^ z8Xc{P^K{1f;OnlEgMs!a*;7+{lq@DgAiE#!o zbwmp-8~<_k;eYJbU*8!wc5yK^5BC`KMXo`3P9iyYT$~ zi6ekG%o5L)l)LaXuDBNLfY}>%z(Z@;;oJJdHv8e7jgQjF@ZFMT-G@y>rMdF?8eKa3 zLIIo2mnK*LA7y6(XZ6&_|CySpX}!}bQd(6+MRrj%%2G|l6Cz7I*I2SNwnjH@Av0VN zk6mPY$R1{h%2pT(A%r5FpPL#z$)z&?_vicj{q8b6|L6bD%WuB-obPtd`JVN6e&6rk zptrFP9ewm|sGf`kxSy~28|-db*dKr$T?2EUc#((?!!s`LnH3fj{o?D3zS_B$`xtk< zEEDR>-*jW>T)O)*LZfo}3y1q5wU!x)!FiYQ4nLk69;uoH5J{ZMQ`c9Hj8u(fa}`O9 z{!W$dx9#PsnadYg+ggiU%Osv_TvLT|6(~Um-T`6mQ3+~of{v~@Gm`kdrP&JyTNq4C z6g_>Wwj+psO)1^iG=TR7i1E}h6-!ypeQSF7G&4lA@p)6k|F+O*9v96cMsrl8>Q(@5 z)Mv|@CAyaay0xlIqq|si7Z_bhr0R_A>@iQb?-!)sO`?ehH1DKo4iU|PMsq}@s*lO) zo-ONE(H$Mo{hp?4BDzLKH=^Q=7&qIoe95^(_?-j%U()!WQZwF1wjLW9sagaON!0KR z+vHx6t$QxVI35(ueIO0d1kF8#FDX&)km3PRJSPgP0UKB^6vcU>_!krvCq)tyX!rlo zY2-Q4%pex*p3b5JWQO+r)TWGU>K5)HOwel~0k@k@y#<->lrIQYJ~&GVhyX( z&i_dCeX53&onB=X?km8ooadF(#B$zHj#gY;;Jzm$nB?Xwx&A+x)zU14sUgBKu2RVg z%itbS;(2~2J1IbLW0k#4s#t9urgVM4WuxO5ez`ADw$u$(*9wTc2&oa@i?$a~z*2aX z#=fQ$IiA{$yINnVd)>G>%d8iv3OYT@$WxN~(=B2dz>&t4?qe#YEYDw${V5)A@K!CJ z+MV+s0M37Srp;)nc&vOT;4wAik??ugg6(DTh#8Om6)(k3Nz*PD?HwWQp`vY#{NsGu zTPVMq1}$^9tqm_0Ovob@I#6$-k`yoHQH_P2O~#%TXGIb^R!htIQgQ}{az4|tB7&SG zC5Ms8>6j&_dC2rF*;gRxSHY4rM3SB@QjP2psnYGNNa7BjX=y)7+UrjTHFA!msaCJ@ zrQNDhJtiLK8;=3pe=r{7vUzM2k7*%~-r`XVj{~wao+O2Wni&slgEjhf5KeyC!LFr` zY*n|PkfnW$%JcpM_aSefNTlkU)wXVAHT*w1-;4Mnj1rkA=FXv?!RZYBNe}WbQ@b|E zpD6*iARwM{ktz+gk;D}|S?2klx42!<#oodD8w&q(l|d+*ebcpw+VCEJD*d_2q43v+ zb9eC4E0bGT^Jh)aEktt>G{IcZ0-CIq$u_Dpck*Z@f}t6LFAO7lWzt$0T@AzfUNsnQ zBt>+GtDKLs2jTu}r0QP)99}XmX-REY4fY4&uU8E&#kMp^J&ujLdd6nEYOwf8sg}8F z@RgYB6RUV?YekRPJvyjPMXH{q$zps(8(z1+7Q66vHMBn}+C>s=0JWN23UjZurT@;C zUhKXjiC^{fb=%e5gJA!)i2u>k8kq;A&g~6L_fP57F}%e1CdG$qS%Eu3YP|>}E~0ae zE(1#3%TF7We_9ms*vR7C_0+s`gW>)fsrpTtzZ1wm-0d97-|Wjj4f$COxu0tNvH5Dq zr4YKqd=1<>s>!{J-6gx075Z6yENe5${TrSt{34LNHYRurp9(X^MiMEW_-F79P-gTx zWPB+VuCNc2!2L1;KZJ+SUJV4FE1s{yB%azFse0UaKE%@s{)=r)*xQE9Qi)kQtuVYB zjO0IjM5Xe-o>l=|7O#!){Lk&^QT&n-<-Ap~y|&*qI-*2&*BC8jZ+JpoLnjTcSDfBRg=G;)Q>;skUKBo%A;4NcW=U(Nnr%#pQsZCt20Ei^! z^VEv%mq^vcET*}|#QG(>WI>sDoAS$lEz@Bz&Mwo5Qt`#dRi-~xrqV!>gTYId=_sfn zGYhEdSJ1B@XEU21X6G2Q>0;J6V78IJ)OF7HU8f3n2)L#0AfDbTPQl};I^KT+@cx^p zZbNM3C?#lN*1Fd0f3V0@U0nuODm(XNf0Ee#@Nd|f?i+I}BKu;7VJ;M=JDD~R#}ROJ z-!ag6N0~Mo_|VC;k*8)={m+rADhd`!oC$$%ccE630n~cJE3Hb?TK)VNt-}6b zhZH{KB68k}ar*FCRo%>i=i^*Jl=^}+sz#~-JurC%iuRwMS)ZS`;SGWyY zG$qi$+X6{E^%IAV0Fi{Y{ZikHR2}s@%U0CS8Yk|8JihpRbME8i`nkw@omU|}Q;#A! zd;{|Yb*ExgKu>*yDozvPav{3+c_z;vqFJS4LhK~pk?#pC)?8bhHQQ_YtA#xaJU+_E zB%DV=eDS~<`@Vdv|ABd*r?%JY`=gU8+QcF%&B+y;B8f}iK?H$Gu^R6vsKO2Bb>iFG z*vRveecy8LOMy_!Z0`%@J6SKqcDh>5S)>E^0&WoTx<^RN{xrW*sUMJPs~|Z#s8Y&8 zQqnFd^zobibDde6!&>gz{z3CsFT_IyzMKn=!1o%T(#!Knn2r z3f&ycr>rGFrGO%UYXmg+53-_|C;WehtiHTcbOv?neqzQZZ2@V?vy69P`A&+Zx?0Fl zSAvRYRpibAF?qOQ6qNULS1_95;6hoPI=RM89XWr1u|dZycypgKJI}5 z?gi4}4ULRPQh*r`tF($B_$cy7xP%1QH*){tcfj)niHy4OWHn^n$W0cVEe=XuZ)8xg znkF{#bi24<(BfpX$h;+?^M@%Hy9q2|h^LOgiQ-z|zQ)*b?y_V}dyd(al;=wHCwL$5 zk>3Jyz#?Y?IZQ)-ZTE{VF{41MTc;5N{YHCyeAJ{dPISPxECtS>m(*J%&Y zl}e)(?DO20#G}jP97_(}1~W6OkIc};6H)sgL;WP`9^k|mx5P;U({$i+=wsrBg-A&u zZJ&pV(_4aJ%q`6$4Y6NK?4(ev<$OtwiN%aL!A6 z7;Q>G58(z8UT#S0tR}PW`Jkwl`Omb>op-WPxRb!@Ji zY8ta{l;ap22i0`^Z&uKOwmO|ADr@ZbybZF(i_F(h%X_)2WK`O5Xk3iGqptYH zgVwk$eP0XLQ~Sw7jHIx<*ibblx-T&h-8jZ=QS^*>-xLJfODaWgA*lwz9l;XgYTp`RDq!9Uz3s zuaT?|GqU?wJ_=-!_Y(Q-h9?U*6n692v6s=^xjZ{GL=mR;3o*0NIf-I1!EoqOw^-jF;lWOJ{1cWE&YL9Ezz zUXm)#N$=#RchV4N;_3$mmAUVuzQfR7a>i8y59>Qi3+0JM|3a(lgEBQ5)8(3{{f(ns z>DaPPZt^4BH75R}6Pa=?J1f8XO}}8TJxr3Ui1@EbCP~(J?mPRt#(imjS7RtRXecLo zYU*w5y>K9uH7p=l-TckC?W55l%b2I|+xlm-MtP;xKiYF5jv7m=0OotrpbZtFi@C zUE7918lfqb4!iL+L{so1KmEh!5>Wm;iE)BU+h7!w`yM6`5oA77PNq*@Sgw2Tp$b9% z?pKjNFcjRlymuhDc_53II1MO9U+)i+=5-@%{_3rGLZaulb^DZpo+-{6FgA{fe40TB|#m4JcM7dn8jYe#;0GE`Ib7sNjsE2 z-mQ5k$J_4>5O`O>*PPLsw_m4~))+!&RIdlB&(j*iFWo+M%4*Ea;JO_bxE@5jInNu( z$m~1M3s>}aiuGZpxPsXQ9uBEj4C4(nh7w=lxo^(ril((_{7<#%{d6;Y%@w=tc@oo^2B0H%2mzpdCEXgu2I@F>pl=Ki#JObvLn z3>e*QjLhIoy&y8dX>d!IQy%hg_*tSarcygA!sX1DN6JAuEBba#D5re9o~ zz)#7fsU=gscfS*$^&2*x37hbokU7FB7ek#?hABcsa8Q0XkL$i=CD zUrbH}485NAmNSF~U$1-)nC=3iJ32$R7~D{l{GNLM%FsQKp{w4E&4(`N-yoo~xxmax z{h5KgOYTwdltnakJF(acGxHqFG_B2SMA5!)6=l_5Ej`^-WrqEa zsY%L|x~CSS0O0 zRY`+xZ@wOLO8o0H%Jn^#X4lUasA!g&gI~+?SgJWyb+2{_+Dz|l!@9RH(w$Mg)a}R< zKlx;8H^N)!SVxUWboF-$w#xX&DFlJylix~hldilJR4lvrcvL;k-Jr5^aM+RsC~0g_ zi`;qCX_BrWcw|P6#aU{csT!PvfZ$;DKFNanr~FL|6Epvo#iek`v>_fa)P^X{WPZRh zR(R!N*Tv_d*4#{MT3L#imThS)*DGFAVXSa-L{FK52oS|icYP@n!<2a%y)k#HY z>HNSRN>+hhy+^79ldno`ksLJaBs*4Lh~Jn}A2F)Mzq_0Cu<2HoWinM4Hll`^E-TY1 z^Ykpr`B|B3lsP;rb8%MYGG+G3%Df{hvrd`KGnsw^^`%ZIdk?44h+3tLs=?=|BmI4y zns;ZaL9J=G+?CTqR3T@>ATYEQNC*w>byfItwwchGyITmDZbH#1utz|*DvRzN(OsFL zn~|Y2)mpk=S@JQ#w5OuOM)`ytVCaW7$HVHG?Da!`sVsvs6h~!cP1jexeBnA-+H1Nw8GE z4Ezaas=l!qtsm-vrK0+wnrgkxiI(iw%7~D^H45u-YZSQ~4jZL7r%`s%fn;llN?pr< zG`mr9S0?5ieeGtDY3I<&EwNUK)YxYJrbiVUEVj`9(=CVM?f}11wZ&-Ze=~C{M4XK- zQLA1Dtom8g6x%Lx1-I#^HXc*>hK7wG&BF%KT!W97Om{*?qOCk^s5?}pYOnm#=q+pn z-BGMmGC57iv6CSUpj15`eEg%Rp`ud|37jX;W_;YfZ%mT*Vy{Rx1LE*O3CF}! z8~C>Av*h9SolPiU7wSlTFo7bz*fPYLSB{k1=Wi7^Kjp*!Uh&Jsp>JC8Dx?j0h$@Rzt)fY|A;L41 zHdVOW>eAJ;)F!;3n)VK>sX|zvf)!K~J&4Ww5*9CFB>%ifWm9?dQ zmTYV86Bi67`4J%L=vr)`kGSJmsECjcyGQ^ zbYGz2NBmYZVtWc_6kHbm0ucKb-VCKa5>VRWK`(U!FWk==o>+Mkl&a6|B;hsjJ4z{! zlfq|K{Ep4`_E*X*OSv2{k`ODehf-%+>KTBsuRH}eiKqB}_gDa&&GPiL9*(E@Z0rzA z6Dv;(vUuw9iXUSidg}M~sY1oiv1h#xEQb%$#0p1F!q&G>@f07D;nTc6_OU0`;;HeG zs`UVo#1A|@-35!M{t>CVp7m91t#_^c<^u%jXCENw>%`>6_W8;Jz)0dLC7d2l?OSnv zJatfPiNa*@QI4*yMG~^2lX!-`>0UMWQ$LeJyp?C| zlr(a$&dP2a#g&4{ZTZPY$#mC~y?TmhkTsMqU{`MglVx5=rp+JgSrOnaxm=&3h|$dM zEY1UX#u(~1@aVR*WDT;}z^FkGg6R`LxdBl4BO zj_`Gz*ve}zpVQV)nPi!a(=UqU@lY`+=A;d?G}aaCa(0J<9>VB@G@>)|E2OFxrxvDM zFk<-%@ZLuvBQx1QX7;4PemC5bo^yZjLGhd7vLwku#*ckr3k~}cm<0q2-ojZWMSpo~ zaVia>fD(Uq0E~n06z5QQg4Sf!h80l~S4%-s^@K&d;T@IYu$-mN$C7;_ve{_!Vm8Xs zMejWRrR9YklGPN^`1X>hP&;G1!#59K5K@(EMBW5)6#aXRmzLs?w0Nq2#pKxe>C91nrtVg1^xU)J*cfv?Y_%L8n3c)sxktrA zF}ik;+0M_jdAd(LHK3wXmdq`zIk0-m8Y_s#(#^GXpfO4K7r<7Zh)%>+% ziIf{~lV2%zu2Rz;?PSFq$AF>Qu#xd_5g#Su;Bv(D+k>ISat+8q(84$6vWyk_k^%w zmsl6sr#^^Jb}{A^En}Eco$I8dhvv~^rQbO8lNx8CM!@i77r>~O`7zc{+0*^XT%%(VmovgnygL{QPn8xg{=kXI zSOyh$439vM8|H=uv!zK;uoJ_Ay#ZeeCLP0q9jdZ6k6Ms`sj!T$Ak)7`H=CaU->LAe z-kHn;IDCxy9t zKb9zuPi9vFL=qqHENkOt!@;Yytag#Axkgq{B(gep0`s+6yvvQ?JZ3mVK3Ld9+5Flr36ooo=pq>2`=p1}a87$)0>)(EWZpl3RU$t;y| z%{oRrKZXfABEd;1@1iFo7a!pmiz`bn!}q%6QY{~o%hFZn&(Yxi#<9@ z-%7UPmEkOv9mC`n(VPYiH;nKOi;-Illg0?*_b_!~O)drg@Xo+Q7*~Ms2g`C+ue}`bl9{^pjr8)6q{VzU6Wnu{StT z^ci)5r5aMR&@A{^1CPaMK zAT!o#EI^kV;JFI3N$wFWqgMONs1Kw~TePudR1W$!m9}Jca<(^&K4Ts)BRB5qgNl^8 z#@8=gfCMTs+h1Y>080fogoObKcaVVm+4`fxjlrUqmS|_n@@l33M^-7{Go>V9z{OYmG`jVB&9<*KMs1>@5R*2Yf6hNyEp$q_y zm#ipC9&aw53uC(n>zGykI_789L-VykJ@_*4(HG?E7r{$YVJG>q>>fuW{vJF($6i{O=v>R3Q%?w zSVUv&PmOTonR1WQy59Xmu}lBlpc9Aak;E?p=!Ri1oR14-s)I4r^ijej2>8N{Cw(b9 z7|umzfd1U~JEvxUo%_z56U==&;_+VohH3A33hYXGuu&-Znc-9!sh=ZvuNu>{1%^Uo=&~fUjtgH(J&7+n%TABV$u1f&v z;5}vrb5gjMnRX{L(>aGyYdVM^E<_*I$H_cx1#qs)lKo=s)!Q{SatK{P3xO_v zVB(A@tBI}WxLIHDs2(gCluxw8G3!KUgP{*5%I<8 zFem1Gee!CVccmKX3P4so^q3>!aK1yFwM)dq8DJ!F6;Jy7+minO7cWiF9jO#7p`YjDYxpJ&Y?*7x96-CRt zNVLn0mV+4@U>VIoHN9m?M;g1s#qQR>VYh`Yr1~&=--OM$G6 z&f2bePO5EKQm}|NNDX<4BxH(AhKWy>C zriMHIhsB}>7Qv;eHvolyE%@HL{beqM8oR%x+VMSphV#8X=JHMfIqQt{=4*rIv&>`2 z%xymNdEbv@Yd$M#U077hYo$EDsD~myyQuRe@8{2gqSpBpX+6}<(lFp&mBM?YVGxk( z%U)8slc^k7w3}#{D>Sn;v!W5qYI8f`UBUX!=8jfWo<_Ie%F;YZ%zTKV`>xhd1Vk7wUVj23eM(@ubw*$*#?+ioX{l-LFCoW@2%sS=)@}=qbG#2RF z(Ze~d3HCO0US@Oyh$MF6X+_%)f}AzetQ#3t;V=&l8sg=R+`1R+o)Wt|#ctg`Qtp`4g!cf`mw-xVcoR<<75TjRvVM zYdAMaMo@r1yrVxcMO4vmP(kSlwsKT$&W*!Os?}y7+r)RZB;-tdEFE&b?lSz(SAx&n zmk*sAuA-`Yd4SdeJnGp#+@G!Ij+RmKD1^ z6(^|$=)Oj=FA-i0z_-;-08m{VQsLX`IZ-uo?;^szAgVk=E{IgM+p2cDwyA$kBQKt% z?nNlQulJS$#Flu^0AfqL(wll}Yq2G&p(2(r-RcYm3s#5&$-?vSbekw+mWktJ5LT@CLx}H3}Q@{?QublR) z@Ly$UaJTqE6t~!FZ{f#*flA7Hs?zH%x+l$;U$FJg6PwIh!#!^pJXCH;MKnX*qc?1m z-Gj~I&@g!D{!*#zL*cD+J;3*t4N?(CMXF})qOQ|?=b)d|LN8{{mGWCWJz zNo~bmv+lc3Kr%KUnIR$hA{i`_KL)BaQzBKKsw;8!A5;SS8Qi|^&p`%WC^2(&JoEJ0 z35v|TpmuP7P&Knk7Q0RMcVT*@`y5n%q`T4tFN|uuao5uesU+2tY`VUDv2&N{??P9B zIayY%dl_cwfv|8fgbhc-)6^_mmt!fRL)fk>jNJE5ad~-Yb(2i`V%HV!?l1-!ugFS_ zL)c$Aj=*a*Pphbw(wHT$a|aL zni6XBDOKiOheQkUGsP6RAXK0d?IiwD6cOzlSi7gvw6YfOXpn;tKM(MBDw4RVeW3oR zfcl((`ZiHtn5Lc}>QPb+*Rpx#}T&=_Zr3qJ6b*(|zGKnp^^EH=8A zdGhMyby!v4qpy@VBKth?dd8Pw80U=-jk5bjxqdtt?+v1x{P5qKD3;P`#EP!2N`yzuYA9xIaA z69(xPIK|l7)=l0W-O<#M*Tx9W;lfjY5u|vg3HoOU{vm>$M6d>ocna6@?;F8VBVY_# zN2Y52L8v@Bms%CO89y zb1q4CJ*04>tovAD6u8F&ZX0NyvX-t1Kix0ifUa0i+z{cy7eFM@(?_2gpf3`7Q}-Do zgV&ZUyYUmL+P=GRf8)tH!x(Upa1F(#1zeR#TDgZr@(mbvg(gz=6N^3B^ zF`twTHE*B)yeXKGKh*$n;Cte>&K+X*wAt+|uC3i@ah)ZuGp!b?w%DA;f)uWAlgUbL zH{qNmoPUGEm+n2y0w$B}?nFt3-?9|duk~V{THpZTJ|WzH5)-;D8a8rQf{liit$KYH z_+wl^3zxNXwQAj$v{!E=vPVQl`0Cd;nF@#hh3qPkwRN|NY`Vzaa#OemG+WFF=bjL^E&XIgxLo`RE|J9X^e9g3 zC!+>`qJPmQ>eEk$p8U2#%X6Dd`C!(!t}z#`LGV6Bc#0%u@-!XI(|#>Xw2CWY zd|4Qb&cpn1UFI_mBAt7#Y3i@bvm7*ZW!2=}v&^PB=KlXnoD{>nSeWi=p6;7k9$)bA z=Ju63#F)7eAdIlQn_=+jg+i0?e{_1|$n378!1 zGwGFP5>EJogk3Id6{rnr=Tsj&f+PYzEbrSh6nHJKB^v~mz~vG)sy@!FyNW0 zz&nL85sV=pSgRieNQ4`nTAb|=sXD+C_U5TNRqMKcLYOun>*&Y9#f=uL_8?m5%6y~S zx@#8QfNZ+Gu7sqs=sJpSHHbmz%Dr1jh1UW#P2#Vhq$Rcy8plAzk-Uz_zM=l?)W1tM^jbP6vFQwp*^0j5`O=ttXIoFrjsIY+|ksJJA#MT(xjYKaa$y@ z8*;29?ctuq^>N6p3;lg~#!Dqa9(5ZWgjsr-iGCZ=E&=F1qHeuAdZ}c^k*d2Gsbd{Y z=3JCf<=;-#d6yYN8$4VB#CoJ#_;y3GM%qs8x*6hjlp(jp!w*0tF^FfH;H(V68W9{P zf*p;3sLD+MVyEjGK*x#=k%WS~`sIg8(>dQd=vJ7sF5k;i>iv|DH3&3_k-X7rjj=I^ zkz7mLcu)3JQ9Dpn09<17^s92l$s9MU|DR5^=(gz5{5I*gqhq+$ms2#a(Hl8i{e3P9 z78aKI%j*rd`ge%t1CrV5CwB{9i_rp+!~(NAtyER4kIi`O6uOoS#oittTke~p@~yZB!M(M0~M2h(3AH90AYDMNAA3GtKyo`V2H2>se-W*o!6#GKMW+;B0)t8+#l*Utk zlFe7<%5=Y!(^QYqUOs=tSdoJE&@#P;s1IhC!?c zk>%~&L%KGPRDDK$`;mlL9-T~k68mY9Y~*pR;eYKeH0}?NH?)uaigVY@%!&fg*_!J| zXjs{ycXTdT?p+Mn-pMoNbY?2b3NJqp3i5MXfx0nbb9-I#YhWl-S_1z9e&H<&n zob@2ZX#@vVk5fmQMK^|BE3r#y)pxkD<6iYZ06H^I3U&?op#30h#W}cyDsjt%-_GzO zTs=4ZKf3wmICn-?3H>++h47%h{Wu4^Vx0=!rl=0PQoQbDO1ZO0N6=NFpym=Z5kbM( z)?zYHUizz9ygA6TJK|RZL=sbZT6Nw5UQX$My38+q0Rlw*lNeW01xSm8((b|B-7l=E zy@QQ!vx)(cL?7cBOb#c9@@vC*(7TA{Fc^77MnfR;Uv0y(k!RQeQ|e4tFUskF3(gNZ zpk-c2CTDH-QpysJBf(DD2xQ(U-}?Li4rH#|YUxqyX_T_>+8KnolzHyr!uaBmEO_j@ z`H|t!{)bd+jxauml}I~rx3`K~z_ENH1tOL*wia2+9r*^a(9Qq*ve*7D7P@6UNmi*_ z$kSZVhjmgf!RM2j^}c8Bc|o06<^(dS6TROWNex)TE~4GAq6T5m2cZ>vroV(i-!VvM zu3T5oKf4yAFz6{N%6`=QVbIUU{=Dz}MB1P@u(1ahldMtAEOi=#_bLpwNCq_6EY>>g z10c8^H7p2{-{p_doFQYVI~41%CFm+Gj88G;Rh{<=+qKCJq5u8`?E3YYXoi&ETSUKeemUeTDuf8v zfRV)4Jd<6AthS_!`9X9C7M*8Ds@}Bx*LZqw@Q9~~Mf;4UJ!Yh^lG(E1{M-NLODNARQ{CRUo-bXm)pj+I}$dgIKg* z7N`(AlHe)Ulf|NyeaB9Aulaj42F4$(MuLE}n=ujBM{IuPWHz26D(x2ltp9krS!tqY z1EK_l@h6W>)S_2yM8{XW&6)z$-1s!X^lT|NAtmfnC#VQJs+?hv+6$$_Jh3|mc0u^N zXY3mqSa%AlJLYP7aY5g6uj=kF`6Y$IBpdSrw48ci`mSL9DtOOM0Fskw5M=tVj5P zE^RDyU8L$9O6L=~wOF&g6{u5>RA`~Jn$IChYC3mVpk}RGNW}y}^h`|+aHi(nCxysz z|L>;2)=lQo(4LMzKQNW^RnJe>P?~lq7X+F6b4QgX#giB&8VMp*NlW@(Nnwz=Rs5hd zttamKb5%cCskU}*N~+fm z$rfcd&lLHC^S8A4J&}}-vRjJ`Zi)J*^w=dBdt(^i?WIMZ5Yi%* zGK|`rT{>zZXS}<)EHL6HR5bS@T8x$!TGg}v2aF{4=4tXvVQmK%GLwsFPp^k?KQ-J| zhTAm6?Pa+2ngN|F5$=|b;I1^>wSbYtmpsz}ekN<%wk93mXOUsl2qO&eGoK%^HU9Wd z@!T(TTU(K=Pqy$Q)*KT%Dh%+mA-0n`JO*9s8dYQX2l~Nl`o;Q$QFyw>*6Zb-p?pJ| zYV^XCYh45@<7R)2YGlI;G8eP(sq}DnHbUL$dR%Pcxo@@pf5gr?_GH-o-(%+t5K8l? zIc={%qCZweun%u>2ie$|NY#@7k;J1sHBXlEktK^5zEb=>7%-kkA1w=lZTpe1!Sr)( zh<>aR^(RBG&&4C>BTsLUlnHuT(nOet2sydol#Zrqs?^r(g z2FyA@*)Oe@Ttn1KJ?=Wy+IK;`{&cy1n?9F@H%Oqnp67o#H#EoblZ0jE`0wF`4e=mj zcN98^#yAd;02e&Xw$4>E-v$o06}5cqMN+VdQa@1q5)=$dfi>t=KvoUJKlED$skG zoOtSlNY$f;_yA8{Cu~=Dz2CA9=i^y%N*o!kjaAId4YN*Ve9FeexH>KLmKAd{ zb%D?d`|^UKvXxwlY3IVrpmry!*R147Q&CeEq@$+Xdx?Dg96=L#BhcF-q71fT?8#FW zeq^NTdn!6MIINI%68QA9K`-2c3ZypumC#8tlu_HBdR(K^uc7C)0kbE2CS(6l!i;-KW4=&ihh zOw$bz-SydYr@FBLoxXmErxXX}=rsOd;g1JDt?H?+d#*0=-K>A18I;X zQp#oIMG_bJny_1I9z9Tu>z~Ge&vw0h{{EOb+;s?kHngcjMY0(Zf4mvlaNOi;lX2k= z+HjW%7wfCzZ(x0+)?fYmZR(*p?*x{tEzqYMjomdTU?M9c6y#q*s=7|kMB6QaS$)dr z^*?&b{HMa6G8(D0s3zXeC=q%bEIlx~Y=17fcchL~5!;yBySc9XbrtFahe@N`O`|;k zIsf1ZC#%U(qIuydaL)#p1*8oL2V?AI6QWv^A$bGYTtMsP-USE~UsEE1Q=EtadPT1W z+r0lr?+5Zc$@HVgY)^dXCTosi*k3?cF#fZW8kYfT$7b z#VH5~swqZ+Unzx)!T8JDsS{MZKc7@f?%`U9m51|n;p^%j{EhZui)pMy2z4b))&3&<-Fp8uo8U!EVf_yjnb z41a7K75r>y$7PbJ~;jCK&B5 zgp#$p7{frD+}UQ(et_;cMj1QnVA82|?~^2Zyju1cZX_Pnq^ez+{}IObT7&JQpRd5$ zeQG1At-Q{n!J_p{JYw-XwpKPcP4%>>?5nj}cS80otp$+qTT5i)u$+Chn{suOJgtTn zH6%*SmA;XY4ECb%64t+*b6kdPNnNnlHk2 zt|Nc#_O&i^X1!;;O$~m~6EwK*(y|0l_(k9++oiW=w<7n(l4subEBGrJci2XaDQQ+4 z4O8dNw9#JtjMg{y=?hnbE*&XR?Z1-fux7OW86YB4fK$11`ok8NM zN=&!cK-#O;4Mkrg)sG8(M787o@K=&`L$i(_C}DW1>K~6o#iw(+NnKb+t%qau3#yi0 zqr=xG>RBUSyW1EPMfQ8)B= z%Y`m>3K;o@@h9IAzhHf%6_sI?>rNxv?I12+HItm}75nlv2B0iqchc?HmGwMd(yFXS zP}XF6U0CS4iT#5{x{ddr0KEU?8ODb>@!u+$zK_|p6wJ#F^ABDG8|Flw64Z!p>P@h` z-z%oXzS0usH`bDLa)q>Em+*V}4(?iHYkUvCSb2t8OE$9t9gL<{An7;{Zdq@4+R1pj zk>U5~0!?CIRnVHQ3oO0wXb20TvjTwiFHg6VFH6exHjp!C^@sFVQw20}gD;O1eke=s z-5Me?a;wZ>oGXyrhk1DCn%phCi7~my^0fF8@+-j_+06$jQ~g}CDp2(Y+GAoHV|0% zE>h?bFx&&G!Cqy4tR6%ki6}Y2khA|n_uD96(0C~@%oHHH&Yl2~L|>lP>?IUT+FavH z%ruep`_qw|Y(t%8dcy-4zUvFNw}E3)bDwp!-KnW!eW^O%-#Do_?m;9|#4BBEpSu;Y z)?JTG+iGQO;b;jOnbme06~BdCHJQiXzZ(_Jd3o z=SPE-b8b#a#vtArY<>K9f)r(6o;mlOz8UwCN2`dF9#ZF-j!NzVK-I(`=&Am&CPoQu zh|t_YJiT(x>@A4U8FqL-fu|;EoYXB~xZ`6UxR`NADV-|sVY*s+KAys-)(nRm?G=$G zo$u5>6wNIDb^W-|H+LIE^mXBhR;|P$Lb{bpYwoP+S>vvE&pZ_LSvTBQ^c@-&#V{`x zrn{P_3OgL8?lbk#dzpOjq{o-MHVe(*sRkn)(ReyRk?b;U zK>eV(YTY%m_bKTDT66oW&2Jv`6`GA=e^<&2RmvAZ@=N*O!y6gmjY4$y1Ux6g(``a2 zPwtz{2jIgtYTVCLjhEyD7;C(iVdFhP0sSlC{|uV(Yv?mYKGMF2ImiU4>8$GiM+~E> zD#CvrKr{9YW=l^}v+2rEb9^vNV^+f!WM`QEfOVRfJY`HSaj)Q)Ub~QBC#ra#TyW0*bG-(5rG zK0@^`?SDX@C0VniLOH>&g@tk&36+I%8cU8gBq^}^A%;Kw#gSj?Nc*Ueu0KfH>38&n z9Lyhh)hxDU-`_;xxXj(D3R7Gun*%x7{LGA}y+u#@3MI+;RDW8#4ZgVPAdsk7M=W1_ z?TgXgy~bjcU?NcB15MGBT0!UbFe(_AptROI|2e{MqQJkeytowEg^wRqy=UA@-v~k| z-GS%$OwKrR#_Jx0P7E1w8iY{tMBNLVtPn~TI^pILxp9C3S8zWGss0}H%!E*~v?OVW zwQxq=L$Q|g6*(rhVF;!5;`KbaSs|1x?S9g-LMWLMEldgj3+nwLnu9YR8UmQ zJSQzP6GCaDsD`JhD%e=N%R(y4+&iRd5JJiC2C8SX(zd?YxpPZso$bRguc4OHvV1pJ zN&VFfH2Zbml2yNtez>8ambGv{(}M0jQM9IY7t6*PyH!d&6@-ivdH-TO(QVj@YzrgK zeE$h2%=LaWi;ESZ0-y39XK2!$^Tt*5!ULB0v_Zt9jmtB%yAseywC|Z?4GXbiHGBp< z8M1u=`5;vmD&3mBJ)2Rl=x#L?AHgDkzFStT(a*IyHK_Ow!dY{dOgL4VMcYy7wWN!- z?lY9@7mOTuDruXRm{7P4oIw3pS*TbZCbqLkXG4l*-O!EpS~@ZiW;tL?#hX^B;t*CnuZqW zsCP)&T{&yXF%9dO@z|IUK8!!~Bkljam&i5S&q|v|nm$Yn;wxFpJaD+Q^^tmsaGD{d zgDX8dBB&M1JU=Znc|#ah>Eo^bkYP@~X?F(mSvY1XDV77%{E9PTr)jb#4xjvGf6n-n zJW-BKzl*ieh#90WQTi}E@>J{i;mLbxER4s;fgqS)G-hpBOSgMs~~lhQumbxeX>$V=ZXz*%Y3m1O6(aKu{C*Y zBF#r&q1T&~(SA~JbV7h@~aO2E8hy4UG#PaI0;8X~QUDb{La(n%MBXA>6 z;aIl`Ylo!yTyx1$m)0(HdC zicEKfLE52i>%UmA1i`beK9Gn^>I$q1_^zZZKOM8n`o}c~F?9Ij*1+3s3T3Flvpp4+ zu1&YcZ{%cFGV{-|7?p3^!AmY?^FPqiXSb0tF$^lzh-g+^UeOfbFV5h;u@?854i z!1V(er+xlS%g*-B5y^_OM$rz#7^ZLIM_EC%z2I4bBhh_0Ms-&KM;rG7I#E!;IG{0t zI>dpP0_&sOdjcIKXrQPE0acI7l3m(RcDeU6t)G#-BR@jftpo?M^MQTYUx6Pj;6
DAP+=Nyv{1!A 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

m{vaK`$QD$jQ+PJij9cEEcmM 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

B+yOKazP{4K56mH#cR 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 z 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 diff --git a/programs/develop/oberon07/GitHub.url b/programs/develop/oberon07/GitHub.url deleted file mode 100644 index 590f82c50..000000000 --- a/programs/develop/oberon07/GitHub.url +++ /dev/null @@ -1,2 +0,0 @@ -[InternetShortcut] -URL=https://github.com/AntKrotov/oberon-07-compiler diff --git a/programs/develop/oberon07/Lib/KolibriOS/API.ob07 b/programs/develop/oberon07/Lib/KolibriOS/API.ob07 index 4f9917132..3e1619a15 100644 --- a/programs/develop/oberon07/Lib/KolibriOS/API.ob07 +++ b/programs/develop/oberon07/Lib/KolibriOS/API.ob07 @@ -12,6 +12,8 @@ IMPORT SYSTEM, K := KOSAPI; CONST + eol* = 0DX + 0AX; + MAX_SIZE = 16 * 400H; HEAP_SIZE = 1 * 100000H; @@ -33,9 +35,8 @@ VAR CriticalSection: CRITICAL_SECTION; - import*, multi: BOOLEAN; + _import*, multi: BOOLEAN; - eol*: ARRAY 3 OF CHAR; base*: INTEGER; @@ -284,24 +285,24 @@ PROCEDURE imp_error; BEGIN OutString("import error: "); IF K.imp_error.error = 1 THEN - OutString("can't load "); OutString(K.imp_error.lib) + OutString("can't load '"); OutString(K.imp_error.lib) ELSIF K.imp_error.error = 2 THEN - OutString("not found "); OutString(K.imp_error.proc); OutString(" in "); OutString(K.imp_error.lib) + OutString("not found '"); OutString(K.imp_error.proc); OutString("' in '"); OutString(K.imp_error.lib) END; + OutString("'"); OutLn END imp_error; -PROCEDURE init* (_import, code: INTEGER); +PROCEDURE init* (import_, code: INTEGER); BEGIN multi := FALSE; - eol[0] := 0DX; eol[1] := 0AX; eol[2] := 0X; base := code - SizeOfHeader; K.sysfunc2(68, 11); InitializeCriticalSection(CriticalSection); K._init; - import := (K.dll_Load(_import) = 0) & (K.imp_error.error = 0); - IF ~import THEN + _import := (K.dll_Load(import_) = 0) & (K.imp_error.error = 0); + IF ~_import THEN imp_error END END init; diff --git a/programs/develop/oberon07/Lib/KolibriOS/ColorDlg.ob07 b/programs/develop/oberon07/Lib/KolibriOS/ColorDlg.ob07 index e993d375c..584b15b3c 100644 --- a/programs/develop/oberon07/Lib/KolibriOS/ColorDlg.ob07 +++ b/programs/develop/oberon07/Lib/KolibriOS/ColorDlg.ob07 @@ -1,5 +1,5 @@ (* - Copyright 2016, 2018 Anton Krotov + Copyright 2016, 2018, 2020 Anton Krotov This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -24,7 +24,7 @@ TYPE DRAW_WINDOW = PROCEDURE; TDialog = RECORD - type, + _type, procinfo, com_area_name, com_area, @@ -61,7 +61,7 @@ BEGIN IF res # NIL THEN res.s_com_area_name := "FFFFFFFF_color_dlg"; res.com_area := 0; - res.type := 0; + res._type := 0; res.color_type := 0; res.procinfo := sys.ADR(res.procinf[0]); res.com_area_name := sys.ADR(res.s_com_area_name[0]); diff --git a/programs/develop/oberon07/Lib/KolibriOS/HOST.ob07 b/programs/develop/oberon07/Lib/KolibriOS/HOST.ob07 index 775291cdd..a3280b46f 100644 --- a/programs/develop/oberon07/Lib/KolibriOS/HOST.ob07 +++ b/programs/develop/oberon07/Lib/KolibriOS/HOST.ob07 @@ -13,7 +13,7 @@ IMPORT SYSTEM, K := KOSAPI, API, RTL; CONST slash* = "/"; - OS* = "KOS"; + eol* = 0DX + 0AX; bit_depth* = RTL.bit_depth; maxint* = RTL.maxint; @@ -24,6 +24,8 @@ CONST TYPE + DAYS = ARRAY 12, 31, 2 OF INTEGER; + FNAME = ARRAY 520 OF CHAR; FS = POINTER TO rFS; @@ -52,11 +54,11 @@ VAR Console: BOOLEAN; + days: DAYS; + Params: ARRAY MAX_PARAM, 2 OF INTEGER; argc*: INTEGER; - eol*: ARRAY 3 OF CHAR; - maxreal*: REAL; @@ -273,6 +275,10 @@ BEGIN END FileOpen; +PROCEDURE chmod* (FName: ARRAY OF CHAR); +END chmod; + + PROCEDURE GetTickCount* (): INTEGER; RETURN K.sysfunc2(26, 9) END GetTickCount; @@ -382,8 +388,8 @@ BEGIN s[j] := c; INC(j) END; - INC(i); - END; + INC(i) + END END; s[j] := 0X END GetArg; @@ -408,9 +414,9 @@ PROCEDURE isRelative* (path: ARRAY OF CHAR): BOOLEAN; END isRelative; -PROCEDURE now* (VAR year, month, day, hour, min, sec: INTEGER); +PROCEDURE UnixTime* (): INTEGER; VAR - date, time: INTEGER; + date, time, year, month, day, hour, min, sec: INTEGER; BEGIN date := K.sysfunc1(29); @@ -446,22 +452,26 @@ BEGIN sec := (time MOD 16) * 10 + sec; time := time DIV 16; - year := year + 2000 -END now; + INC(year, 2000) - -PROCEDURE UnixTime* (): INTEGER; - RETURN 0 + RETURN ((year - 1970) * 365 + days[month - 1, day - 1, ORD(year DIV 4 = 0)] + (year - 1969) DIV 4) * 86400 + hour * 3600 + min * 60 + sec END UnixTime; +PROCEDURE splitf* (x: REAL; VAR a, b: INTEGER): INTEGER; +BEGIN + SYSTEM.GET32(SYSTEM.ADR(x), a); + SYSTEM.GET32(SYSTEM.ADR(x) + 4, b) + RETURN a +END splitf; + + PROCEDURE d2s* (x: REAL): INTEGER; VAR h, l, s, e: INTEGER; BEGIN - SYSTEM.GET(SYSTEM.ADR(x), l); - SYSTEM.GET(SYSTEM.ADR(x) + 4, h); + e := splitf(x, l, h); s := ASR(h, 31) MOD 2; e := (h DIV 100000H) MOD 2048; @@ -480,7 +490,7 @@ BEGIN l := 0 ELSIF e = 2047 THEN e := 1151; - IF (h MOD 100000H # 0) OR (l # 0) THEN + IF (h MOD 100000H # 0) OR (BITS(l) * {0..31} # {}) THEN h := 80000H; l := 0 END @@ -491,21 +501,55 @@ BEGIN END d2s; -PROCEDURE splitf* (x: REAL; VAR a, b: INTEGER): INTEGER; -BEGIN - SYSTEM.GET(SYSTEM.ADR(x), a); - SYSTEM.GET(SYSTEM.ADR(x) + 4, b) - RETURN a -END splitf; - +PROCEDURE init (VAR days: DAYS); +VAR + i, j, n0, n1: INTEGER; BEGIN - eol[0] := 0DX; eol[1] := 0AX; eol[2] := 0X; + + FOR i := 0 TO 11 DO + FOR j := 0 TO 30 DO + days[i, j, 0] := 0; + days[i, j, 1] := 0; + END + END; + + days[ 1, 28, 0] := -1; + + FOR i := 0 TO 1 DO + days[ 1, 29, i] := -1; + days[ 1, 30, i] := -1; + days[ 3, 30, i] := -1; + days[ 5, 30, i] := -1; + days[ 8, 30, i] := -1; + days[10, 30, i] := -1; + END; + + n0 := 0; + n1 := 0; + FOR i := 0 TO 11 DO + FOR j := 0 TO 30 DO + IF days[i, j, 0] = 0 THEN + days[i, j, 0] := n0; + INC(n0) + END; + IF days[i, j, 1] = 0 THEN + days[i, j, 1] := n1; + INC(n1) + END + END + END; + maxreal := 1.9; PACK(maxreal, 1023); - Console := API.import; + Console := API._import; IF Console THEN con_init(-1, -1, -1, -1, SYSTEM.SADR("Oberon-07 for KolibriOS")) END; ParamParse +END init; + + +BEGIN + init(days) END HOST. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/KolibriOS/Math.ob07 b/programs/develop/oberon07/Lib/KolibriOS/Math.ob07 index b1fe62acc..d6056af74 100644 --- a/programs/develop/oberon07/Lib/KolibriOS/Math.ob07 +++ b/programs/develop/oberon07/Lib/KolibriOS/Math.ob07 @@ -1,18 +1,8 @@ (* - Copyright 2013, 2014, 2018, 2019 Anton Krotov + BSD 2-Clause License - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . + Copyright (c) 2013-2014, 2018-2020 Anton Krotov + All rights reserved. *) MODULE Math; @@ -235,6 +225,16 @@ BEGIN END frac; +PROCEDURE sqri* (x: INTEGER): INTEGER; + RETURN x * x +END sqri; + + +PROCEDURE sqrr* (x: REAL): REAL; + RETURN x * x +END sqrr; + + PROCEDURE arcsin* (x: REAL): REAL; RETURN arctan2(x, sqrt(1.0 - x * x)) END arcsin; @@ -349,6 +349,40 @@ BEGIN END power; +PROCEDURE ipower* (base: REAL; exponent: INTEGER): REAL; +VAR + i: INTEGER; + a: REAL; + +BEGIN + a := 1.0; + + IF base # 0.0 THEN + IF exponent # 0 THEN + IF exponent < 0 THEN + base := 1.0 / base + END; + i := ABS(exponent); + WHILE i > 0 DO + WHILE ~ODD(i) DO + i := LSR(i, 1); + base := sqrr(base) + END; + DEC(i); + a := a * base + END + ELSE + a := 1.0 + END + ELSE + ASSERT(exponent > 0); + a := 0.0 + END + + RETURN a +END ipower; + + PROCEDURE sgn* (x: REAL): INTEGER; VAR res: INTEGER; @@ -381,4 +415,36 @@ BEGIN END fact; +PROCEDURE DegToRad* (x: REAL): REAL; + RETURN x * (pi / 180.0) +END DegToRad; + + +PROCEDURE RadToDeg* (x: REAL): REAL; + RETURN x * (180.0 / pi) +END RadToDeg; + + +(* Return hypotenuse of triangle *) +PROCEDURE hypot* (x, y: REAL): REAL; +VAR + a: REAL; + +BEGIN + x := ABS(x); + y := ABS(y); + IF x > y THEN + a := x * sqrt(1.0 + sqrr(y / x)) + ELSE + IF x > 0.0 THEN + a := y * sqrt(1.0 + sqrr(x / y)) + ELSE + a := y + END + END + + RETURN a +END hypot; + + END Math. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/KolibriOS/OpenDlg.ob07 b/programs/develop/oberon07/Lib/KolibriOS/OpenDlg.ob07 index 9bffd20f2..82d6bfbc3 100644 --- a/programs/develop/oberon07/Lib/KolibriOS/OpenDlg.ob07 +++ b/programs/develop/oberon07/Lib/KolibriOS/OpenDlg.ob07 @@ -1,5 +1,5 @@ (* - Copyright 2016, 2018 Anton Krotov + Copyright 2016, 2018, 2020 Anton Krotov This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -24,7 +24,7 @@ TYPE DRAW_WINDOW = PROCEDURE; TDialog = RECORD - type, + _type, procinfo, com_area_name, com_area, @@ -66,7 +66,7 @@ BEGIN END END Show; -PROCEDURE Create*(draw_window: DRAW_WINDOW; type: INTEGER; def_path, filter: ARRAY OF CHAR): Dialog; +PROCEDURE Create*(draw_window: DRAW_WINDOW; _type: INTEGER; def_path, filter: ARRAY OF CHAR): Dialog; VAR res: Dialog; n, i: INTEGER; PROCEDURE replace(VAR str: ARRAY OF CHAR; c1, c2: CHAR); @@ -88,7 +88,7 @@ BEGIN IF res.filter_area # NIL THEN res.s_com_area_name := "FFFFFFFF_open_dialog"; res.com_area := 0; - res.type := type; + res._type := _type; res.draw_window := draw_window; COPY(def_path, res.s_dir_default_path); COPY(filter, res.filter_area.filter); diff --git a/programs/develop/oberon07/Lib/KolibriOS/RTL.ob07 b/programs/develop/oberon07/Lib/KolibriOS/RTL.ob07 index 0929a5678..5f9e16808 100644 --- a/programs/develop/oberon07/Lib/KolibriOS/RTL.ob07 +++ b/programs/develop/oberon07/Lib/KolibriOS/RTL.ob07 @@ -372,33 +372,29 @@ END PCharToStr; PROCEDURE IntToStr (x: INTEGER; VAR str: ARRAY OF CHAR); VAR - i, a, b: INTEGER; - c: CHAR; + i, a: INTEGER; BEGIN i := 0; + a := x; REPEAT - str[i] := CHR(x MOD 10 + ORD("0")); - x := x DIV 10; - INC(i) - UNTIL x = 0; + INC(i); + a := a DIV 10 + UNTIL a = 0; - a := 0; - b := i - 1; - WHILE a < b DO - c := str[a]; - str[a] := str[b]; - str[b] := c; - INC(a); - DEC(b) - END; - str[i] := 0X + str[i] := 0X; + + REPEAT + DEC(i); + str[i] := CHR(x MOD 10 + ORD("0")); + x := x DIV 10 + UNTIL x = 0 END IntToStr; PROCEDURE append (VAR s1: ARRAY OF CHAR; s2: ARRAY OF CHAR); VAR - n1, n2, i, j: INTEGER; + n1, n2: INTEGER; BEGIN n1 := LENGTH(s1); @@ -406,19 +402,12 @@ BEGIN ASSERT(n1 + n2 < LEN(s1)); - i := 0; - j := n1; - WHILE i < n2 DO - s1[j] := s2[i]; - INC(i); - INC(j) - END; - - s1[j] := 0X + SYSTEM.MOVE(SYSTEM.ADR(s2[0]), SYSTEM.ADR(s1[n1]), n2); + s1[n1 + n2] := 0X END append; -PROCEDURE [stdcall] _error* (module, err, line: INTEGER); +PROCEDURE [stdcall] _error* (modnum, _module, err, line: INTEGER); VAR s, temp: ARRAY 1024 OF CHAR; @@ -437,10 +426,8 @@ BEGIN |11: s := "BYTE out of range" END; - append(s, API.eol); - - append(s, "module: "); PCharToStr(module, temp); append(s, temp); append(s, API.eol); - append(s, "line: "); IntToStr(line, temp); append(s, temp); + append(s, API.eol + "module: "); PCharToStr(_module, temp); append(s, temp); + append(s, API.eol + "line: "); IntToStr(line, temp); append(s, temp); API.DebugMsg(SYSTEM.ADR(s[0]), name); diff --git a/programs/develop/oberon07/Lib/KolibriOS/libimg.ob07 b/programs/develop/oberon07/Lib/KolibriOS/libimg.ob07 index 425f74034..35e9f5dd5 100644 --- a/programs/develop/oberon07/Lib/KolibriOS/libimg.ob07 +++ b/programs/develop/oberon07/Lib/KolibriOS/libimg.ob07 @@ -1,5 +1,5 @@ (* - Copyright 2016, 2018 KolibriOS team + Copyright 2016, 2018, 2020 KolibriOS team This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -203,7 +203,7 @@ VAR - img_create *: PROCEDURE (width, height, type: INTEGER): INTEGER; + img_create *: PROCEDURE (width, height, _type: INTEGER): INTEGER; (* ;;------------------------------------------------------------------------------------------------;; ;? creates an Image structure and initializes some its fields ;; diff --git a/programs/develop/oberon07/Lib/Linux32/API.ob07 b/programs/develop/oberon07/Lib/Linux32/API.ob07 index 0415cdbd0..754147401 100644 --- a/programs/develop/oberon07/Lib/Linux32/API.ob07 +++ b/programs/develop/oberon07/Lib/Linux32/API.ob07 @@ -12,54 +12,34 @@ IMPORT SYSTEM; CONST - RTLD_LAZY* = 1; + eol* = 0AX; + BIT_DEPTH* = 32; + RTLD_LAZY = 1; + TYPE - TP* = ARRAY 2 OF INTEGER; - SOFINI* = PROCEDURE; + SOFINI = PROCEDURE; VAR - eol*: ARRAY 2 OF CHAR; - MainParam*: INTEGER; + MainParam*, libc*: INTEGER; - libc*, librt*: INTEGER; + dlopen* : PROCEDURE [linux] (filename, flag: INTEGER): INTEGER; + dlsym* : PROCEDURE [linux] (handle, symbol: INTEGER): INTEGER; - dlopen* : PROCEDURE [linux] (filename, flag: INTEGER): INTEGER; - dlsym* : PROCEDURE [linux] (handle, symbol: INTEGER): INTEGER; - - stdout*, - stdin*, - stderr* : INTEGER; - - malloc* : PROCEDURE [linux] (size: INTEGER): INTEGER; - free* : PROCEDURE [linux] (ptr: INTEGER); - _exit* : PROCEDURE [linux] (code: INTEGER); - puts* : PROCEDURE [linux] (pStr: INTEGER); - fwrite*, - fread* : PROCEDURE [linux] (buffer, bytes, blocks, file: INTEGER): INTEGER; - fopen* : PROCEDURE [linux] (fname, fmode: INTEGER): INTEGER; - fclose* : PROCEDURE [linux] (file: INTEGER): INTEGER; - - clock_gettime* : PROCEDURE [linux] (clock_id: INTEGER; VAR tp: TP): INTEGER; - time* : PROCEDURE [linux] (ptr: INTEGER): INTEGER; + exit*, + exit_thread* : PROCEDURE [linux] (code: INTEGER); + puts : PROCEDURE [linux] (pStr: INTEGER); + malloc : PROCEDURE [linux] (size: INTEGER): INTEGER; + free : PROCEDURE [linux] (ptr: INTEGER); fini: SOFINI; -PROCEDURE putc* (c: CHAR); -VAR - res: INTEGER; - -BEGIN - res := fwrite(SYSTEM.ADR(c), 1, 1, stdout) -END putc; - - PROCEDURE DebugMsg* (lpText, lpCaption: INTEGER); BEGIN puts(lpCaption); @@ -94,7 +74,7 @@ BEGIN END _DISPOSE; -PROCEDURE GetProcAdr (lib: INTEGER; name: ARRAY OF CHAR; VarAdr: INTEGER); +PROCEDURE GetSym (lib: INTEGER; name: ARRAY OF CHAR; VarAdr: INTEGER); VAR sym: INTEGER; @@ -102,7 +82,7 @@ BEGIN sym := dlsym(lib, SYSTEM.ADR(name[0])); ASSERT(sym # 0); SYSTEM.PUT(VarAdr, sym) -END GetProcAdr; +END GetSym; PROCEDURE init* (sp, code: INTEGER); @@ -111,42 +91,16 @@ BEGIN SYSTEM.GET(code - 1000H - SYSTEM.SIZE(INTEGER) * 2, dlopen); SYSTEM.GET(code - 1000H - SYSTEM.SIZE(INTEGER), dlsym); MainParam := sp; - eol := 0AX; libc := dlopen(SYSTEM.SADR("libc.so.6"), RTLD_LAZY); - GetProcAdr(libc, "malloc", SYSTEM.ADR(malloc)); - GetProcAdr(libc, "free", SYSTEM.ADR(free)); - GetProcAdr(libc, "exit", SYSTEM.ADR(_exit)); - GetProcAdr(libc, "stdout", SYSTEM.ADR(stdout)); - GetProcAdr(libc, "stdin", SYSTEM.ADR(stdin)); - GetProcAdr(libc, "stderr", SYSTEM.ADR(stderr)); - SYSTEM.GET(stdout - SYSTEM.SIZE(INTEGER), stdout); - SYSTEM.GET(stdin - SYSTEM.SIZE(INTEGER), stdin); - SYSTEM.GET(stderr - SYSTEM.SIZE(INTEGER), stderr); - GetProcAdr(libc, "puts", SYSTEM.ADR(puts)); - GetProcAdr(libc, "fwrite", SYSTEM.ADR(fwrite)); - GetProcAdr(libc, "fread", SYSTEM.ADR(fread)); - GetProcAdr(libc, "fopen", SYSTEM.ADR(fopen)); - GetProcAdr(libc, "fclose", SYSTEM.ADR(fclose)); - GetProcAdr(libc, "time", SYSTEM.ADR(time)); - - librt := dlopen(SYSTEM.SADR("librt.so.1"), RTLD_LAZY); - GetProcAdr(librt, "clock_gettime", SYSTEM.ADR(clock_gettime)) + GetSym(libc, "exit", SYSTEM.ADR(exit_thread)); + exit := exit_thread; + GetSym(libc, "puts", SYSTEM.ADR(puts)); + GetSym(libc, "malloc", SYSTEM.ADR(malloc)); + GetSym(libc, "free", SYSTEM.ADR(free)); END init; -PROCEDURE exit* (code: INTEGER); -BEGIN - _exit(code) -END exit; - - -PROCEDURE exit_thread* (code: INTEGER); -BEGIN - _exit(code) -END exit_thread; - - PROCEDURE dllentry* (hinstDLL, fdwReason, lpvReserved: INTEGER): INTEGER; RETURN 0 END dllentry; diff --git a/programs/develop/oberon07/Lib/Linux32/Args.ob07 b/programs/develop/oberon07/Lib/Linux32/Args.ob07 new file mode 100644 index 000000000..cb3379a78 --- /dev/null +++ b/programs/develop/oberon07/Lib/Linux32/Args.ob07 @@ -0,0 +1,70 @@ +(* + BSD 2-Clause License + + Copyright (c) 2020, Anton Krotov + All rights reserved. +*) + +MODULE Args; + +IMPORT SYSTEM, API; + + +VAR + + argc*, envc*: INTEGER; + + +PROCEDURE GetArg* (n: INTEGER; VAR s: ARRAY OF CHAR); +VAR + i, len, ptr: INTEGER; + c: CHAR; + +BEGIN + i := 0; + len := LEN(s) - 1; + IF (0 <= n) & (n <= argc + envc) & (n # argc) & (len > 0) THEN + SYSTEM.GET(API.MainParam + (n + 1) * SYSTEM.SIZE(INTEGER), ptr); + REPEAT + SYSTEM.GET(ptr, c); + s[i] := c; + INC(i); + INC(ptr) + UNTIL (c = 0X) OR (i = len) + END; + s[i] := 0X +END GetArg; + + +PROCEDURE GetEnv* (n: INTEGER; VAR s: ARRAY OF CHAR); +BEGIN + IF (0 <= n) & (n < envc) THEN + GetArg(n + argc + 1, s) + ELSE + s[0] := 0X + END +END GetEnv; + + +PROCEDURE init; +VAR + ptr: INTEGER; + +BEGIN + IF API.MainParam # 0 THEN + envc := -1; + SYSTEM.GET(API.MainParam, argc); + REPEAT + SYSTEM.GET(API.MainParam + (envc + argc + 3) * SYSTEM.SIZE(INTEGER), ptr); + INC(envc) + UNTIL ptr = 0 + ELSE + envc := 0; + argc := 0 + END +END init; + + +BEGIN + init +END Args. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux32/File.ob07 b/programs/develop/oberon07/Lib/Linux32/File.ob07 new file mode 100644 index 000000000..f200014f5 --- /dev/null +++ b/programs/develop/oberon07/Lib/Linux32/File.ob07 @@ -0,0 +1,132 @@ +(* + BSD 2-Clause License + + Copyright (c) 2020, Anton Krotov + All rights reserved. +*) + +MODULE File; + +IMPORT SYSTEM, Libdl, API; + + +CONST + + OPEN_R* = "rb"; OPEN_W* = "wb"; OPEN_RW* = "r+b"; + SEEK_BEG* = 0; SEEK_CUR* = 1; SEEK_END* = 2; + + +VAR + + fwrite, + fread : PROCEDURE [linux] (buffer, bytes, blocks, file: INTEGER): INTEGER; + fseek : PROCEDURE [linux] (file, offset, origin: INTEGER): INTEGER; + ftell : PROCEDURE [linux] (file: INTEGER): INTEGER; + fopen : PROCEDURE [linux] (fname, fmode: INTEGER): INTEGER; + fclose : PROCEDURE [linux] (file: INTEGER): INTEGER; + remove : PROCEDURE [linux] (fname: INTEGER): INTEGER; + + +PROCEDURE GetSym (lib: INTEGER; name: ARRAY OF CHAR; VarAdr: INTEGER); +VAR + sym: INTEGER; + +BEGIN + sym := Libdl.sym(lib, name); + ASSERT(sym # 0); + SYSTEM.PUT(VarAdr, sym) +END GetSym; + + +PROCEDURE init; +VAR + libc: INTEGER; + +BEGIN + libc := Libdl.open("libc.so.6", Libdl.LAZY); + ASSERT(libc # 0); + + GetSym(libc, "fread", SYSTEM.ADR(fread)); + GetSym(libc, "fwrite", SYSTEM.ADR(fwrite)); + GetSym(libc, "fseek", SYSTEM.ADR(fseek)); + GetSym(libc, "ftell", SYSTEM.ADR(ftell)); + GetSym(libc, "fopen", SYSTEM.ADR(fopen)); + GetSym(libc, "fclose", SYSTEM.ADR(fclose)); + GetSym(libc, "remove", SYSTEM.ADR(remove)); +END init; + + +PROCEDURE Delete* (FName: ARRAY OF CHAR): BOOLEAN; + RETURN remove(SYSTEM.ADR(FName[0])) = 0 +END Delete; + + +PROCEDURE Close* (F: INTEGER); +BEGIN + F := fclose(F) +END Close; + + +PROCEDURE Open* (FName, Mode: ARRAY OF CHAR): INTEGER; + RETURN fopen(SYSTEM.ADR(FName[0]), SYSTEM.ADR(Mode[0])) +END Open; + + +PROCEDURE Create* (FName: ARRAY OF CHAR): INTEGER; + RETURN Open(FName, OPEN_W) +END Create; + + +PROCEDURE Seek* (F, Offset, Origin: INTEGER): INTEGER; +VAR + res: INTEGER; + +BEGIN + IF fseek(F, Offset, Origin) = 0 THEN + res := ftell(F) + ELSE + res := -1 + END + + RETURN res +END Seek; + + +PROCEDURE Write* (F, Buffer, Count: INTEGER): INTEGER; + RETURN fwrite(Buffer, 1, Count, F) +END Write; + + +PROCEDURE Read* (F, Buffer, Count: INTEGER): INTEGER; + RETURN fread(Buffer, 1, Count, F) +END Read; + + +PROCEDURE Load* (FName: ARRAY OF CHAR; VAR Size: INTEGER): INTEGER; +VAR + res, n, F: INTEGER; + +BEGIN + res := 0; + F := Open(FName, OPEN_R); + + IF F > 0 THEN + Size := Seek(F, 0, SEEK_END); + n := Seek(F, 0, SEEK_BEG); + res := API._NEW(Size); + IF (res = 0) OR (Read(F, res, Size) # Size) THEN + IF res # 0 THEN + res := API._DISPOSE(res); + Size := 0 + END + END; + Close(F) + END + + RETURN res +END Load; + + +BEGIN + init +END File. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux32/HOST.ob07 b/programs/develop/oberon07/Lib/Linux32/HOST.ob07 index 2851c0cab..53676801f 100644 --- a/programs/develop/oberon07/Lib/Linux32/HOST.ob07 +++ b/programs/develop/oberon07/Lib/Linux32/HOST.ob07 @@ -13,25 +13,42 @@ IMPORT SYSTEM, API, RTL; CONST slash* = "/"; - OS* = "LINUX"; + eol* = 0AX; bit_depth* = RTL.bit_depth; maxint* = RTL.maxint; minint* = RTL.minint; + RTLD_LAZY = 1; + + +TYPE + + TP = ARRAY 2 OF INTEGER; + VAR + maxreal*: REAL; + argc: INTEGER; - eol*: ARRAY 2 OF CHAR; + libc, librt: INTEGER; - maxreal*: REAL; + stdout: INTEGER; + + fread, fwrite : PROCEDURE [linux] (buffer, bytes, blocks, file: INTEGER): INTEGER; + fopen : PROCEDURE [linux] (fname, fmode: INTEGER): INTEGER; + fclose : PROCEDURE [linux] (file: INTEGER): INTEGER; + _chmod : PROCEDURE [linux] (fname: INTEGER; mode: SET): INTEGER; + time : PROCEDURE [linux] (ptr: INTEGER): INTEGER; + clock_gettime : PROCEDURE [linux] (clock_id: INTEGER; VAR tp: TP): INTEGER; + exit : PROCEDURE [linux] (code: INTEGER); PROCEDURE ExitProcess* (code: INTEGER); BEGIN - API.exit(code) + exit(code) END ExitProcess; @@ -75,7 +92,7 @@ VAR res: INTEGER; BEGIN - res := API.fread(SYSTEM.ADR(Buffer[0]), 1, bytes, F); + res := fread(SYSTEM.ADR(Buffer[0]), 1, bytes, F); IF res <= 0 THEN res := -1 END @@ -89,7 +106,7 @@ VAR res: INTEGER; BEGIN - res := API.fwrite(SYSTEM.ADR(Buffer[0]), 1, bytes, F); + res := fwrite(SYSTEM.ADR(Buffer[0]), 1, bytes, F); IF res <= 0 THEN res := -1 END @@ -99,34 +116,45 @@ END FileWrite; PROCEDURE FileCreate* (FName: ARRAY OF CHAR): INTEGER; - RETURN API.fopen(SYSTEM.ADR(FName[0]), SYSTEM.SADR("wb")) + RETURN fopen(SYSTEM.ADR(FName[0]), SYSTEM.SADR("wb")) END FileCreate; PROCEDURE FileClose* (File: INTEGER); BEGIN - File := API.fclose(File) + File := fclose(File) END FileClose; +PROCEDURE chmod* (FName: ARRAY OF CHAR); +VAR + res: INTEGER; +BEGIN + res := _chmod(SYSTEM.ADR(FName[0]), {0, 2..8}) (* rwxrwxr-x *) +END chmod; + + PROCEDURE FileOpen* (FName: ARRAY OF CHAR): INTEGER; - RETURN API.fopen(SYSTEM.ADR(FName[0]), SYSTEM.SADR("rb")) + RETURN fopen(SYSTEM.ADR(FName[0]), SYSTEM.SADR("rb")) END FileOpen; PROCEDURE OutChar* (c: CHAR); +VAR + res: INTEGER; + BEGIN - API.putc(c) + res := fwrite(SYSTEM.ADR(c), 1, 1, stdout) END OutChar; PROCEDURE GetTickCount* (): INTEGER; VAR - tp: API.TP; + tp: TP; res: INTEGER; BEGIN - IF API.clock_gettime(0, tp) = 0 THEN + IF clock_gettime(0, tp) = 0 THEN res := tp[0] * 100 + tp[1] DIV 10000000 ELSE res := 0 @@ -141,22 +169,25 @@ PROCEDURE isRelative* (path: ARRAY OF CHAR): BOOLEAN; END isRelative; -PROCEDURE now* (VAR year, month, day, hour, min, sec: INTEGER); -END now; - - PROCEDURE UnixTime* (): INTEGER; - RETURN API.time(0) + RETURN time(0) END UnixTime; +PROCEDURE splitf* (x: REAL; VAR a, b: INTEGER): INTEGER; +BEGIN + SYSTEM.GET32(SYSTEM.ADR(x), a); + SYSTEM.GET32(SYSTEM.ADR(x) + 4, b) + RETURN a +END splitf; + + PROCEDURE d2s* (x: REAL): INTEGER; VAR h, l, s, e: INTEGER; BEGIN - SYSTEM.GET(SYSTEM.ADR(x), l); - SYSTEM.GET(SYSTEM.ADR(x) + 4, h); + e := splitf(x, l, h); s := ASR(h, 31) MOD 2; e := (h DIV 100000H) MOD 2048; @@ -175,7 +206,7 @@ BEGIN l := 0 ELSIF e = 2047 THEN e := 1151; - IF (h MOD 100000H # 0) OR (l # 0) THEN + IF (h MOD 100000H # 0) OR (BITS(l) * {0..31} # {}) THEN h := 80000H; l := 0 END @@ -186,23 +217,32 @@ BEGIN END d2s; -PROCEDURE splitf* (x: REAL; VAR a, b: INTEGER): INTEGER; +PROCEDURE GetSym (lib: INTEGER; name: ARRAY OF CHAR; VarAdr: INTEGER); VAR - res: INTEGER; + sym: INTEGER; BEGIN - a := 0; - b := 0; - SYSTEM.MOVE(SYSTEM.ADR(x), SYSTEM.ADR(a), 4); - SYSTEM.MOVE(SYSTEM.ADR(x) + 4, SYSTEM.ADR(b), 4); - SYSTEM.GET(SYSTEM.ADR(x), res) - RETURN res -END splitf; + sym := API.dlsym(lib, SYSTEM.ADR(name[0])); + ASSERT(sym # 0); + SYSTEM.PUT(VarAdr, sym) +END GetSym; BEGIN - eol := 0AX; maxreal := 1.9; PACK(maxreal, 1023); - SYSTEM.GET(API.MainParam, argc) + SYSTEM.GET(API.MainParam, argc); + + libc := API.libc; + GetSym(libc, "fread", SYSTEM.ADR(fread)); + GetSym(libc, "fwrite", SYSTEM.ADR(fwrite)); + GetSym(libc, "fopen", SYSTEM.ADR(fopen)); + GetSym(libc, "fclose", SYSTEM.ADR(fclose)); + GetSym(libc, "chmod", SYSTEM.ADR(_chmod)); + GetSym(libc, "time", SYSTEM.ADR(time)); + GetSym(libc, "exit", SYSTEM.ADR(exit)); + GetSym(libc, "stdout", SYSTEM.ADR(stdout)); SYSTEM.GET(stdout - SYSTEM.SIZE(INTEGER), stdout); + + librt := API.dlopen(SYSTEM.SADR("librt.so.1"), RTLD_LAZY); + GetSym(librt, "clock_gettime", SYSTEM.ADR(clock_gettime)) END HOST. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux32/In.ob07 b/programs/develop/oberon07/Lib/Linux32/In.ob07 new file mode 100644 index 000000000..f5b487754 --- /dev/null +++ b/programs/develop/oberon07/Lib/Linux32/In.ob07 @@ -0,0 +1,85 @@ +(* + BSD 2-Clause License + + Copyright (c) 2020, Anton Krotov + All rights reserved. +*) + +MODULE In; + +IMPORT SYSTEM, Libdl; + + +CONST + + MAX_LEN = 10240; + + +VAR + + Done*: BOOLEAN; + s: ARRAY MAX_LEN + 4 OF CHAR; + + sscanf: PROCEDURE [linux] (buf: INTEGER; fmt: INTEGER; adr: INTEGER): INTEGER; + gets: PROCEDURE [linux] (buf: INTEGER); + + +PROCEDURE String* (VAR str: ARRAY OF CHAR); +BEGIN + gets(SYSTEM.ADR(s[0])); + COPY(s, str); + str[LEN(str) - 1] := 0X; + Done := TRUE +END String; + + +PROCEDURE Int* (VAR x: INTEGER); +BEGIN + String(s); + Done := sscanf(SYSTEM.ADR(s[0]), SYSTEM.SADR("%d"), SYSTEM.ADR(x)) = 1 +END Int; + + +PROCEDURE Real* (VAR x: REAL); +BEGIN + String(s); + Done := sscanf(SYSTEM.ADR(s[0]), SYSTEM.SADR("%lf"), SYSTEM.ADR(x)) = 1 +END Real; + + +PROCEDURE Char* (VAR x: CHAR); +BEGIN + String(s); + x := s[0] +END Char; + + +PROCEDURE Ln*; +BEGIN + String(s) +END Ln; + + +PROCEDURE Open*; +BEGIN + Done := TRUE +END Open; + + +PROCEDURE init; +VAR + libc: INTEGER; + +BEGIN + libc := Libdl.open("libc.so.6", Libdl.LAZY); + ASSERT(libc # 0); + SYSTEM.PUT(SYSTEM.ADR(sscanf), Libdl.sym(libc, "sscanf")); + ASSERT(sscanf # NIL); + SYSTEM.PUT(SYSTEM.ADR(gets), Libdl.sym(libc, "gets")); + ASSERT(gets # NIL); +END init; + + +BEGIN + init +END In. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux32/LINAPI.ob07 b/programs/develop/oberon07/Lib/Linux32/LINAPI.ob07 index 31348bcad..497660a26 100644 --- a/programs/develop/oberon07/Lib/Linux32/LINAPI.ob07 +++ b/programs/develop/oberon07/Lib/Linux32/LINAPI.ob07 @@ -7,19 +7,17 @@ MODULE LINAPI; -IMPORT SYSTEM, API; +IMPORT SYSTEM, API, Libdl; TYPE - TP* = API.TP; - SOFINI* = API.SOFINI; + TP* = ARRAY 2 OF INTEGER; + SOFINI* = PROCEDURE; VAR - argc*, envc*: INTEGER; - libc*, librt*: INTEGER; stdout*, @@ -39,79 +37,44 @@ VAR clock_gettime* : PROCEDURE [linux] (clock_id: INTEGER; VAR tp: TP): INTEGER; -PROCEDURE GetArg* (n: INTEGER; VAR s: ARRAY OF CHAR); -VAR - i, len, ptr: INTEGER; - c: CHAR; - -BEGIN - i := 0; - len := LEN(s) - 1; - IF (0 <= n) & (n <= argc + envc) & (n # argc) & (len > 0) THEN - SYSTEM.GET(API.MainParam + (n + 1) * SYSTEM.SIZE(INTEGER), ptr); - REPEAT - SYSTEM.GET(ptr, c); - s[i] := c; - INC(i); - INC(ptr) - UNTIL (c = 0X) OR (i = len) - END; - s[i] := 0X -END GetArg; - - -PROCEDURE GetEnv* (n: INTEGER; VAR s: ARRAY OF CHAR); -BEGIN - IF (0 <= n) & (n < envc) THEN - GetArg(n + argc + 1, s) - ELSE - s[0] := 0X - END -END GetEnv; - - PROCEDURE SetFini* (ProcFini: SOFINI); BEGIN API.SetFini(ProcFini) END SetFini; -PROCEDURE init; +PROCEDURE GetSym (lib: INTEGER; name: ARRAY OF CHAR; VarAdr: INTEGER); VAR - ptr: INTEGER; + sym: INTEGER; BEGIN - IF API.MainParam # 0 THEN - envc := -1; - SYSTEM.GET(API.MainParam, argc); - REPEAT - SYSTEM.GET(API.MainParam + (envc + argc + 3) * SYSTEM.SIZE(INTEGER), ptr); - INC(envc) - UNTIL ptr = 0 - ELSE - envc := 0; - argc := 0 - END; + sym := Libdl.sym(lib, name); + ASSERT(sym # 0); + SYSTEM.PUT(VarAdr, sym) +END GetSym; + +PROCEDURE init; +BEGIN libc := API.libc; - stdout := API.stdout; - stdin := API.stdin; - stderr := API.stderr; + GetSym(libc, "exit", SYSTEM.ADR(exit)); + GetSym(libc, "puts", SYSTEM.ADR(puts)); + GetSym(libc, "malloc", SYSTEM.ADR(malloc)); + GetSym(libc, "free", SYSTEM.ADR(free)); + GetSym(libc, "fread", SYSTEM.ADR(fread)); + GetSym(libc, "fwrite", SYSTEM.ADR(fwrite)); + GetSym(libc, "fopen", SYSTEM.ADR(fopen)); + GetSym(libc, "fclose", SYSTEM.ADR(fclose)); + GetSym(libc, "time", SYSTEM.ADR(time)); - malloc := API.malloc; - free := API.free; - exit := API._exit; - puts := API.puts; - fwrite := API.fwrite; - fread := API.fread; - fopen := API.fopen; - fclose := API.fclose; - time := API.time; + GetSym(libc, "stdout", SYSTEM.ADR(stdout)); SYSTEM.GET(stdout - SYSTEM.SIZE(INTEGER), stdout); + GetSym(libc, "stdin", SYSTEM.ADR(stdin)); SYSTEM.GET(stdin - SYSTEM.SIZE(INTEGER), stdin); + GetSym(libc, "stderr", SYSTEM.ADR(stderr)); SYSTEM.GET(stderr - SYSTEM.SIZE(INTEGER), stderr); - librt := API.librt; + librt := Libdl.open("librt.so.1", Libdl.LAZY); - clock_gettime := API.clock_gettime + GetSym(librt, "clock_gettime", SYSTEM.ADR(clock_gettime)) END init; diff --git a/programs/develop/oberon07/Lib/Linux32/Math.ob07 b/programs/develop/oberon07/Lib/Linux32/Math.ob07 index 25950952b..beb3bb884 100644 --- a/programs/develop/oberon07/Lib/Linux32/Math.ob07 +++ b/programs/develop/oberon07/Lib/Linux32/Math.ob07 @@ -1,18 +1,8 @@ (* - Copyright 2013, 2014, 2018, 2019 Anton Krotov + BSD 2-Clause License - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . + Copyright (c) 2013-2014, 2018-2020 Anton Krotov + All rights reserved. *) MODULE Math; @@ -235,6 +225,16 @@ BEGIN END frac; +PROCEDURE sqri* (x: INTEGER): INTEGER; + RETURN x * x +END sqri; + + +PROCEDURE sqrr* (x: REAL): REAL; + RETURN x * x +END sqrr; + + PROCEDURE arcsin* (x: REAL): REAL; RETURN arctan2(x, sqrt(1.0 - x * x)) END arcsin; @@ -349,6 +349,40 @@ BEGIN END power; +PROCEDURE ipower* (base: REAL; exponent: INTEGER): REAL; +VAR + i: INTEGER; + a: REAL; + +BEGIN + a := 1.0; + + IF base # 0.0 THEN + IF exponent # 0 THEN + IF exponent < 0 THEN + base := 1.0 / base + END; + i := ABS(exponent); + WHILE i > 0 DO + WHILE ~ODD(i) DO + i := LSR(i, 1); + base := sqrr(base) + END; + DEC(i); + a := a * base + END + ELSE + a := 1.0 + END + ELSE + ASSERT(exponent > 0); + a := 0.0 + END + + RETURN a +END ipower; + + PROCEDURE sgn* (x: REAL): INTEGER; VAR res: INTEGER; @@ -381,4 +415,36 @@ BEGIN END fact; +PROCEDURE DegToRad* (x: REAL): REAL; + RETURN x * (pi / 180.0) +END DegToRad; + + +PROCEDURE RadToDeg* (x: REAL): REAL; + RETURN x * (180.0 / pi) +END RadToDeg; + + +(* Return hypotenuse of triangle *) +PROCEDURE hypot* (x, y: REAL): REAL; +VAR + a: REAL; + +BEGIN + x := ABS(x); + y := ABS(y); + IF x > y THEN + a := x * sqrt(1.0 + sqrr(y / x)) + ELSE + IF x > 0.0 THEN + a := y * sqrt(1.0 + sqrr(x / y)) + ELSE + a := y + END + END + + RETURN a +END hypot; + + END Math. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux32/Out.ob07 b/programs/develop/oberon07/Lib/Linux32/Out.ob07 index 1bb3f2325..c723cf0e5 100644 --- a/programs/develop/oberon07/Lib/Linux32/Out.ob07 +++ b/programs/develop/oberon07/Lib/Linux32/Out.ob07 @@ -1,277 +1,77 @@ (* - Copyright 2013, 2014, 2017, 2018, 2019 Anton Krotov + BSD 2-Clause License - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . + Copyright (c) 2020, Anton Krotov + All rights reserved. *) MODULE Out; -IMPORT sys := SYSTEM, API; +IMPORT SYSTEM, Libdl; -CONST - - d = 1.0 - 5.0E-12; VAR - Realp: PROCEDURE (x: REAL; width: INTEGER); + printf1: PROCEDURE [linux] (fmt: INTEGER; x: INTEGER); + printf2: PROCEDURE [linux] (fmt: INTEGER; width, x: INTEGER); + printf3: PROCEDURE [linux] (fmt: INTEGER; width, precision: INTEGER; x: REAL); -PROCEDURE Char*(x: CHAR); +PROCEDURE Char* (x: CHAR); BEGIN - API.putc(x) + printf1(SYSTEM.SADR("%c"), ORD(x)) END Char; -PROCEDURE String*(s: ARRAY OF CHAR); -VAR - i: INTEGER; - +PROCEDURE String* (s: ARRAY OF CHAR); BEGIN - i := 0; - WHILE (i < LEN(s)) & (s[i] # 0X) DO - Char(s[i]); - INC(i) - END + printf2(SYSTEM.SADR("%.*s"), LENGTH(s), SYSTEM.ADR(s[0])) END String; -PROCEDURE WriteInt(x, n: INTEGER); -VAR i: INTEGER; a: ARRAY 16 OF CHAR; neg: BOOLEAN; -BEGIN - i := 0; - IF n < 1 THEN - n := 1 - END; - IF x < 0 THEN - x := -x; - DEC(n); - neg := TRUE - END; - REPEAT - a[i] := CHR(x MOD 10 + ORD("0")); - x := x DIV 10; - INC(i) - UNTIL x = 0; - WHILE n > i DO - Char(" "); - DEC(n) - END; - IF neg THEN - Char("-") - END; - REPEAT - DEC(i); - Char(a[i]) - UNTIL i = 0 -END WriteInt; - -PROCEDURE IsNan(AValue: REAL): BOOLEAN; -VAR h, l: SET; -BEGIN - sys.GET(sys.ADR(AValue), l); - sys.GET(sys.ADR(AValue) + 4, h) - RETURN (h * {20..30} = {20..30}) & ((h * {0..19} # {}) OR (l * {0..31} # {})) -END IsNan; - -PROCEDURE IsInf(x: REAL): BOOLEAN; - RETURN ABS(x) = sys.INF() -END IsInf; - -PROCEDURE Int*(x, width: INTEGER); -VAR i: INTEGER; -BEGIN - IF x # 80000000H THEN - WriteInt(x, width) - ELSE - FOR i := 12 TO width DO - Char(20X) - END; - String("-2147483648") - END -END Int; - -PROCEDURE OutInf(x: REAL; width: INTEGER); -VAR s: ARRAY 5 OF CHAR; i: INTEGER; -BEGIN - IF IsNan(x) THEN - s := "Nan"; - INC(width) - ELSIF IsInf(x) & (x > 0.0) THEN - s := "+Inf" - ELSIF IsInf(x) & (x < 0.0) THEN - s := "-Inf" - END; - FOR i := 1 TO width - 4 DO - Char(" ") - END; - String(s) -END OutInf; - PROCEDURE Ln*; BEGIN - Char(0AX) + printf1(SYSTEM.SADR("%s"), SYSTEM.SADR(0AX)) END Ln; -PROCEDURE _FixReal(x: REAL; width, p: INTEGER); -VAR e, len, i: INTEGER; y: REAL; minus: BOOLEAN; -BEGIN - IF IsNan(x) OR IsInf(x) THEN - OutInf(x, width) - ELSIF p < 0 THEN - Realp(x, width) - ELSE - len := 0; - minus := FALSE; - IF x < 0.0 THEN - minus := TRUE; - INC(len); - x := ABS(x) - END; - e := 0; - WHILE x >= 10.0 DO - x := x / 10.0; - INC(e) - END; - IF e >= 0 THEN - len := len + e + p + 1; - IF x > 9.0 + d THEN - INC(len) - END; - IF p > 0 THEN - INC(len) - END; - ELSE - len := len + p + 2 - END; - FOR i := 1 TO width - len DO - Char(" ") - END; - IF minus THEN - Char("-") - END; - y := x; - WHILE (y < 1.0) & (y # 0.0) DO - y := y * 10.0; - DEC(e) - END; - IF e < 0 THEN - IF x - FLT(FLOOR(x)) > d THEN - Char("1"); - x := 0.0 - ELSE - Char("0"); - x := x * 10.0 - END - ELSE - WHILE e >= 0 DO - IF x - FLT(FLOOR(x)) > d THEN - IF x > 9.0 THEN - String("10") - ELSE - Char(CHR(FLOOR(x) + ORD("0") + 1)) - END; - x := 0.0 - ELSE - Char(CHR(FLOOR(x) + ORD("0"))); - x := (x - FLT(FLOOR(x))) * 10.0 - END; - DEC(e) - END - END; - IF p > 0 THEN - Char(".") - END; - WHILE p > 0 DO - IF x - FLT(FLOOR(x)) > d THEN - Char(CHR(FLOOR(x) + ORD("0") + 1)); - x := 0.0 - ELSE - Char(CHR(FLOOR(x) + ORD("0"))); - x := (x - FLT(FLOOR(x))) * 10.0 - END; - DEC(p) - END - END -END _FixReal; - -PROCEDURE Real*(x: REAL; width: INTEGER); -VAR e, n, i: INTEGER; minus: BOOLEAN; +PROCEDURE Int* (x, width: INTEGER); BEGIN - Realp := Real; - IF IsNan(x) OR IsInf(x) THEN - OutInf(x, width) - ELSE - e := 0; - n := 0; - IF width > 23 THEN - n := width - 23; - width := 23 - ELSIF width < 9 THEN - width := 9 - END; - width := width - 5; - IF x < 0.0 THEN - x := -x; - minus := TRUE - ELSE - minus := FALSE - END; - WHILE x >= 10.0 DO - x := x / 10.0; - INC(e) - END; - WHILE (x < 1.0) & (x # 0.0) DO - x := x * 10.0; - DEC(e) - END; - IF x > 9.0 + d THEN - x := 1.0; - INC(e) - END; - FOR i := 1 TO n DO - Char(" ") - END; - IF minus THEN - x := -x - END; - _FixReal(x, width, width - 3); - Char("E"); - IF e >= 0 THEN - Char("+") - ELSE - Char("-"); - e := ABS(e) - END; - IF e < 100 THEN - Char("0") - END; - IF e < 10 THEN - Char("0") - END; - Int(e, 0) - END + printf2(SYSTEM.SADR("%*d"), width, x) +END Int; + + +PROCEDURE Real* (x: REAL; width: INTEGER); +BEGIN + printf3(SYSTEM.SADR("%*.*E"), width, MAX(MIN(width - 8, 15), 1), x) END Real; -PROCEDURE FixReal*(x: REAL; width, p: INTEGER); + +PROCEDURE FixReal* (x: REAL; width, precision: INTEGER); BEGIN - Realp := Real; - _FixReal(x, width, p) + printf3(SYSTEM.SADR("%*.*f"), width, precision, x) END FixReal; + PROCEDURE Open*; END Open; + +PROCEDURE init; +VAR + libc, printf: INTEGER; + +BEGIN + libc := Libdl.open("libc.so.6", Libdl.LAZY); + ASSERT(libc # 0); + printf := Libdl.sym(libc, "printf"); + ASSERT(printf # 0); + SYSTEM.PUT(SYSTEM.ADR(printf1), printf); + SYSTEM.PUT(SYSTEM.ADR(printf2), printf); + SYSTEM.PUT(SYSTEM.ADR(printf3), printf); +END init; + + +BEGIN + init END Out. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux32/RTL.ob07 b/programs/develop/oberon07/Lib/Linux32/RTL.ob07 index 0929a5678..5f9e16808 100644 --- a/programs/develop/oberon07/Lib/Linux32/RTL.ob07 +++ b/programs/develop/oberon07/Lib/Linux32/RTL.ob07 @@ -372,33 +372,29 @@ END PCharToStr; PROCEDURE IntToStr (x: INTEGER; VAR str: ARRAY OF CHAR); VAR - i, a, b: INTEGER; - c: CHAR; + i, a: INTEGER; BEGIN i := 0; + a := x; REPEAT - str[i] := CHR(x MOD 10 + ORD("0")); - x := x DIV 10; - INC(i) - UNTIL x = 0; + INC(i); + a := a DIV 10 + UNTIL a = 0; - a := 0; - b := i - 1; - WHILE a < b DO - c := str[a]; - str[a] := str[b]; - str[b] := c; - INC(a); - DEC(b) - END; - str[i] := 0X + str[i] := 0X; + + REPEAT + DEC(i); + str[i] := CHR(x MOD 10 + ORD("0")); + x := x DIV 10 + UNTIL x = 0 END IntToStr; PROCEDURE append (VAR s1: ARRAY OF CHAR; s2: ARRAY OF CHAR); VAR - n1, n2, i, j: INTEGER; + n1, n2: INTEGER; BEGIN n1 := LENGTH(s1); @@ -406,19 +402,12 @@ BEGIN ASSERT(n1 + n2 < LEN(s1)); - i := 0; - j := n1; - WHILE i < n2 DO - s1[j] := s2[i]; - INC(i); - INC(j) - END; - - s1[j] := 0X + SYSTEM.MOVE(SYSTEM.ADR(s2[0]), SYSTEM.ADR(s1[n1]), n2); + s1[n1 + n2] := 0X END append; -PROCEDURE [stdcall] _error* (module, err, line: INTEGER); +PROCEDURE [stdcall] _error* (modnum, _module, err, line: INTEGER); VAR s, temp: ARRAY 1024 OF CHAR; @@ -437,10 +426,8 @@ BEGIN |11: s := "BYTE out of range" END; - append(s, API.eol); - - append(s, "module: "); PCharToStr(module, temp); append(s, temp); append(s, API.eol); - append(s, "line: "); IntToStr(line, temp); append(s, temp); + append(s, API.eol + "module: "); PCharToStr(_module, temp); append(s, temp); + append(s, API.eol + "line: "); IntToStr(line, temp); append(s, temp); API.DebugMsg(SYSTEM.ADR(s[0]), name); diff --git a/programs/develop/oberon07/Lib/Linux64/API.ob07 b/programs/develop/oberon07/Lib/Linux64/API.ob07 index 8d845678d..fb0a96bfa 100644 --- a/programs/develop/oberon07/Lib/Linux64/API.ob07 +++ b/programs/develop/oberon07/Lib/Linux64/API.ob07 @@ -12,54 +12,34 @@ IMPORT SYSTEM; CONST - RTLD_LAZY* = 1; + eol* = 0AX; + BIT_DEPTH* = 64; + RTLD_LAZY = 1; + TYPE - TP* = ARRAY 2 OF INTEGER; - SOFINI* = PROCEDURE; + SOFINI = PROCEDURE; VAR - eol*: ARRAY 2 OF CHAR; - MainParam*: INTEGER; + MainParam*, libc*: INTEGER; - libc*, librt*: INTEGER; + dlopen* : PROCEDURE [linux] (filename, flag: INTEGER): INTEGER; + dlsym* : PROCEDURE [linux] (handle, symbol: INTEGER): INTEGER; - dlopen* : PROCEDURE [linux] (filename, flag: INTEGER): INTEGER; - dlsym* : PROCEDURE [linux] (handle, symbol: INTEGER): INTEGER; - - stdout*, - stdin*, - stderr* : INTEGER; - - malloc* : PROCEDURE [linux] (size: INTEGER): INTEGER; - free* : PROCEDURE [linux] (ptr: INTEGER); - _exit* : PROCEDURE [linux] (code: INTEGER); - puts* : PROCEDURE [linux] (pStr: INTEGER); - fwrite*, - fread* : PROCEDURE [linux] (buffer, bytes, blocks, file: INTEGER): INTEGER; - fopen* : PROCEDURE [linux] (fname, fmode: INTEGER): INTEGER; - fclose* : PROCEDURE [linux] (file: INTEGER): INTEGER; - - clock_gettime* : PROCEDURE [linux] (clock_id: INTEGER; VAR tp: TP): INTEGER; - time* : PROCEDURE [linux] (ptr: INTEGER): INTEGER; + exit*, + exit_thread* : PROCEDURE [linux] (code: INTEGER); + puts : PROCEDURE [linux] (pStr: INTEGER); + malloc : PROCEDURE [linux] (size: INTEGER): INTEGER; + free : PROCEDURE [linux] (ptr: INTEGER); fini: SOFINI; -PROCEDURE putc* (c: CHAR); -VAR - res: INTEGER; - -BEGIN - res := fwrite(SYSTEM.ADR(c), 1, 1, stdout) -END putc; - - PROCEDURE DebugMsg* (lpText, lpCaption: INTEGER); BEGIN puts(lpCaption); @@ -94,7 +74,7 @@ BEGIN END _DISPOSE; -PROCEDURE GetProcAdr (lib: INTEGER; name: ARRAY OF CHAR; VarAdr: INTEGER); +PROCEDURE GetSym (lib: INTEGER; name: ARRAY OF CHAR; VarAdr: INTEGER); VAR sym: INTEGER; @@ -102,7 +82,7 @@ BEGIN sym := dlsym(lib, SYSTEM.ADR(name[0])); ASSERT(sym # 0); SYSTEM.PUT(VarAdr, sym) -END GetProcAdr; +END GetSym; PROCEDURE init* (sp, code: INTEGER); @@ -111,42 +91,16 @@ BEGIN SYSTEM.GET(code - 1000H - SYSTEM.SIZE(INTEGER) * 2, dlopen); SYSTEM.GET(code - 1000H - SYSTEM.SIZE(INTEGER), dlsym); MainParam := sp; - eol := 0AX; libc := dlopen(SYSTEM.SADR("libc.so.6"), RTLD_LAZY); - GetProcAdr(libc, "malloc", SYSTEM.ADR(malloc)); - GetProcAdr(libc, "free", SYSTEM.ADR(free)); - GetProcAdr(libc, "exit", SYSTEM.ADR(_exit)); - GetProcAdr(libc, "stdout", SYSTEM.ADR(stdout)); - GetProcAdr(libc, "stdin", SYSTEM.ADR(stdin)); - GetProcAdr(libc, "stderr", SYSTEM.ADR(stderr)); - SYSTEM.GET(stdout - SYSTEM.SIZE(INTEGER), stdout); - SYSTEM.GET(stdin - SYSTEM.SIZE(INTEGER), stdin); - SYSTEM.GET(stderr - SYSTEM.SIZE(INTEGER), stderr); - GetProcAdr(libc, "puts", SYSTEM.ADR(puts)); - GetProcAdr(libc, "fwrite", SYSTEM.ADR(fwrite)); - GetProcAdr(libc, "fread", SYSTEM.ADR(fread)); - GetProcAdr(libc, "fopen", SYSTEM.ADR(fopen)); - GetProcAdr(libc, "fclose", SYSTEM.ADR(fclose)); - GetProcAdr(libc, "time", SYSTEM.ADR(time)); - - librt := dlopen(SYSTEM.SADR("librt.so.1"), RTLD_LAZY); - GetProcAdr(librt, "clock_gettime", SYSTEM.ADR(clock_gettime)) + GetSym(libc, "exit", SYSTEM.ADR(exit_thread)); + exit := exit_thread; + GetSym(libc, "puts", SYSTEM.ADR(puts)); + GetSym(libc, "malloc", SYSTEM.ADR(malloc)); + GetSym(libc, "free", SYSTEM.ADR(free)); END init; -PROCEDURE exit* (code: INTEGER); -BEGIN - _exit(code) -END exit; - - -PROCEDURE exit_thread* (code: INTEGER); -BEGIN - _exit(code) -END exit_thread; - - PROCEDURE dllentry* (hinstDLL, fdwReason, lpvReserved: INTEGER): INTEGER; RETURN 0 END dllentry; diff --git a/programs/develop/oberon07/Lib/Linux64/Args.ob07 b/programs/develop/oberon07/Lib/Linux64/Args.ob07 new file mode 100644 index 000000000..cb3379a78 --- /dev/null +++ b/programs/develop/oberon07/Lib/Linux64/Args.ob07 @@ -0,0 +1,70 @@ +(* + BSD 2-Clause License + + Copyright (c) 2020, Anton Krotov + All rights reserved. +*) + +MODULE Args; + +IMPORT SYSTEM, API; + + +VAR + + argc*, envc*: INTEGER; + + +PROCEDURE GetArg* (n: INTEGER; VAR s: ARRAY OF CHAR); +VAR + i, len, ptr: INTEGER; + c: CHAR; + +BEGIN + i := 0; + len := LEN(s) - 1; + IF (0 <= n) & (n <= argc + envc) & (n # argc) & (len > 0) THEN + SYSTEM.GET(API.MainParam + (n + 1) * SYSTEM.SIZE(INTEGER), ptr); + REPEAT + SYSTEM.GET(ptr, c); + s[i] := c; + INC(i); + INC(ptr) + UNTIL (c = 0X) OR (i = len) + END; + s[i] := 0X +END GetArg; + + +PROCEDURE GetEnv* (n: INTEGER; VAR s: ARRAY OF CHAR); +BEGIN + IF (0 <= n) & (n < envc) THEN + GetArg(n + argc + 1, s) + ELSE + s[0] := 0X + END +END GetEnv; + + +PROCEDURE init; +VAR + ptr: INTEGER; + +BEGIN + IF API.MainParam # 0 THEN + envc := -1; + SYSTEM.GET(API.MainParam, argc); + REPEAT + SYSTEM.GET(API.MainParam + (envc + argc + 3) * SYSTEM.SIZE(INTEGER), ptr); + INC(envc) + UNTIL ptr = 0 + ELSE + envc := 0; + argc := 0 + END +END init; + + +BEGIN + init +END Args. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux64/File.ob07 b/programs/develop/oberon07/Lib/Linux64/File.ob07 new file mode 100644 index 000000000..f200014f5 --- /dev/null +++ b/programs/develop/oberon07/Lib/Linux64/File.ob07 @@ -0,0 +1,132 @@ +(* + BSD 2-Clause License + + Copyright (c) 2020, Anton Krotov + All rights reserved. +*) + +MODULE File; + +IMPORT SYSTEM, Libdl, API; + + +CONST + + OPEN_R* = "rb"; OPEN_W* = "wb"; OPEN_RW* = "r+b"; + SEEK_BEG* = 0; SEEK_CUR* = 1; SEEK_END* = 2; + + +VAR + + fwrite, + fread : PROCEDURE [linux] (buffer, bytes, blocks, file: INTEGER): INTEGER; + fseek : PROCEDURE [linux] (file, offset, origin: INTEGER): INTEGER; + ftell : PROCEDURE [linux] (file: INTEGER): INTEGER; + fopen : PROCEDURE [linux] (fname, fmode: INTEGER): INTEGER; + fclose : PROCEDURE [linux] (file: INTEGER): INTEGER; + remove : PROCEDURE [linux] (fname: INTEGER): INTEGER; + + +PROCEDURE GetSym (lib: INTEGER; name: ARRAY OF CHAR; VarAdr: INTEGER); +VAR + sym: INTEGER; + +BEGIN + sym := Libdl.sym(lib, name); + ASSERT(sym # 0); + SYSTEM.PUT(VarAdr, sym) +END GetSym; + + +PROCEDURE init; +VAR + libc: INTEGER; + +BEGIN + libc := Libdl.open("libc.so.6", Libdl.LAZY); + ASSERT(libc # 0); + + GetSym(libc, "fread", SYSTEM.ADR(fread)); + GetSym(libc, "fwrite", SYSTEM.ADR(fwrite)); + GetSym(libc, "fseek", SYSTEM.ADR(fseek)); + GetSym(libc, "ftell", SYSTEM.ADR(ftell)); + GetSym(libc, "fopen", SYSTEM.ADR(fopen)); + GetSym(libc, "fclose", SYSTEM.ADR(fclose)); + GetSym(libc, "remove", SYSTEM.ADR(remove)); +END init; + + +PROCEDURE Delete* (FName: ARRAY OF CHAR): BOOLEAN; + RETURN remove(SYSTEM.ADR(FName[0])) = 0 +END Delete; + + +PROCEDURE Close* (F: INTEGER); +BEGIN + F := fclose(F) +END Close; + + +PROCEDURE Open* (FName, Mode: ARRAY OF CHAR): INTEGER; + RETURN fopen(SYSTEM.ADR(FName[0]), SYSTEM.ADR(Mode[0])) +END Open; + + +PROCEDURE Create* (FName: ARRAY OF CHAR): INTEGER; + RETURN Open(FName, OPEN_W) +END Create; + + +PROCEDURE Seek* (F, Offset, Origin: INTEGER): INTEGER; +VAR + res: INTEGER; + +BEGIN + IF fseek(F, Offset, Origin) = 0 THEN + res := ftell(F) + ELSE + res := -1 + END + + RETURN res +END Seek; + + +PROCEDURE Write* (F, Buffer, Count: INTEGER): INTEGER; + RETURN fwrite(Buffer, 1, Count, F) +END Write; + + +PROCEDURE Read* (F, Buffer, Count: INTEGER): INTEGER; + RETURN fread(Buffer, 1, Count, F) +END Read; + + +PROCEDURE Load* (FName: ARRAY OF CHAR; VAR Size: INTEGER): INTEGER; +VAR + res, n, F: INTEGER; + +BEGIN + res := 0; + F := Open(FName, OPEN_R); + + IF F > 0 THEN + Size := Seek(F, 0, SEEK_END); + n := Seek(F, 0, SEEK_BEG); + res := API._NEW(Size); + IF (res = 0) OR (Read(F, res, Size) # Size) THEN + IF res # 0 THEN + res := API._DISPOSE(res); + Size := 0 + END + END; + Close(F) + END + + RETURN res +END Load; + + +BEGIN + init +END File. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux64/HOST.ob07 b/programs/develop/oberon07/Lib/Linux64/HOST.ob07 index 96bf051d5..66ab8b698 100644 --- a/programs/develop/oberon07/Lib/Linux64/HOST.ob07 +++ b/programs/develop/oberon07/Lib/Linux64/HOST.ob07 @@ -13,25 +13,42 @@ IMPORT SYSTEM, API, RTL; CONST slash* = "/"; - OS* = "LINUX"; + eol* = 0AX; bit_depth* = RTL.bit_depth; maxint* = RTL.maxint; minint* = RTL.minint; + RTLD_LAZY = 1; + + +TYPE + + TP = ARRAY 2 OF INTEGER; + VAR + maxreal*: REAL; + argc: INTEGER; - eol*: ARRAY 2 OF CHAR; + libc, librt: INTEGER; - maxreal*: REAL; + stdout: INTEGER; + + fread, fwrite : PROCEDURE [linux] (buffer, bytes, blocks, file: INTEGER): INTEGER; + fopen : PROCEDURE [linux] (fname, fmode: INTEGER): INTEGER; + fclose : PROCEDURE [linux] (file: INTEGER): INTEGER; + _chmod : PROCEDURE [linux] (fname: INTEGER; mode: SET): INTEGER; + time : PROCEDURE [linux] (ptr: INTEGER): INTEGER; + clock_gettime : PROCEDURE [linux] (clock_id: INTEGER; VAR tp: TP): INTEGER; + exit : PROCEDURE [linux] (code: INTEGER); PROCEDURE ExitProcess* (code: INTEGER); BEGIN - API.exit(code) + exit(code) END ExitProcess; @@ -75,7 +92,7 @@ VAR res: INTEGER; BEGIN - res := API.fread(SYSTEM.ADR(Buffer[0]), 1, bytes, F); + res := fread(SYSTEM.ADR(Buffer[0]), 1, bytes, F); IF res <= 0 THEN res := -1 END @@ -89,7 +106,7 @@ VAR res: INTEGER; BEGIN - res := API.fwrite(SYSTEM.ADR(Buffer[0]), 1, bytes, F); + res := fwrite(SYSTEM.ADR(Buffer[0]), 1, bytes, F); IF res <= 0 THEN res := -1 END @@ -99,34 +116,45 @@ END FileWrite; PROCEDURE FileCreate* (FName: ARRAY OF CHAR): INTEGER; - RETURN API.fopen(SYSTEM.ADR(FName[0]), SYSTEM.SADR("wb")) + RETURN fopen(SYSTEM.ADR(FName[0]), SYSTEM.SADR("wb")) END FileCreate; PROCEDURE FileClose* (File: INTEGER); BEGIN - File := API.fclose(File) + File := fclose(File) END FileClose; +PROCEDURE chmod* (FName: ARRAY OF CHAR); +VAR + res: INTEGER; +BEGIN + res := _chmod(SYSTEM.ADR(FName[0]), {0, 2..8}) (* rwxrwxr-x *) +END chmod; + + PROCEDURE FileOpen* (FName: ARRAY OF CHAR): INTEGER; - RETURN API.fopen(SYSTEM.ADR(FName[0]), SYSTEM.SADR("rb")) + RETURN fopen(SYSTEM.ADR(FName[0]), SYSTEM.SADR("rb")) END FileOpen; PROCEDURE OutChar* (c: CHAR); +VAR + res: INTEGER; + BEGIN - API.putc(c) + res := fwrite(SYSTEM.ADR(c), 1, 1, stdout) END OutChar; PROCEDURE GetTickCount* (): INTEGER; VAR - tp: API.TP; + tp: TP; res: INTEGER; BEGIN - IF API.clock_gettime(0, tp) = 0 THEN + IF clock_gettime(0, tp) = 0 THEN res := tp[0] * 100 + tp[1] DIV 10000000 ELSE res := 0 @@ -141,22 +169,31 @@ PROCEDURE isRelative* (path: ARRAY OF CHAR): BOOLEAN; END isRelative; -PROCEDURE now* (VAR year, month, day, hour, min, sec: INTEGER); -END now; - - PROCEDURE UnixTime* (): INTEGER; - RETURN API.time(0) + RETURN time(0) END UnixTime; +PROCEDURE splitf* (x: REAL; VAR a, b: INTEGER): INTEGER; +VAR + res: INTEGER; + +BEGIN + a := 0; + b := 0; + SYSTEM.GET32(SYSTEM.ADR(x), a); + SYSTEM.GET32(SYSTEM.ADR(x) + 4, b); + SYSTEM.GET(SYSTEM.ADR(x), res) + RETURN res +END splitf; + + PROCEDURE d2s* (x: REAL): INTEGER; VAR h, l, s, e: INTEGER; BEGIN - SYSTEM.GET(SYSTEM.ADR(x), l); - SYSTEM.GET(SYSTEM.ADR(x) + 4, h); + e := splitf(x, l, h); s := ASR(h, 31) MOD 2; e := (h DIV 100000H) MOD 2048; @@ -186,23 +223,32 @@ BEGIN END d2s; -PROCEDURE splitf* (x: REAL; VAR a, b: INTEGER): INTEGER; +PROCEDURE GetSym (lib: INTEGER; name: ARRAY OF CHAR; VarAdr: INTEGER); VAR - res: INTEGER; + sym: INTEGER; BEGIN - a := 0; - b := 0; - SYSTEM.MOVE(SYSTEM.ADR(x), SYSTEM.ADR(a), 4); - SYSTEM.MOVE(SYSTEM.ADR(x) + 4, SYSTEM.ADR(b), 4); - SYSTEM.GET(SYSTEM.ADR(x), res) - RETURN res -END splitf; + sym := API.dlsym(lib, SYSTEM.ADR(name[0])); + ASSERT(sym # 0); + SYSTEM.PUT(VarAdr, sym) +END GetSym; BEGIN - eol := 0AX; maxreal := 1.9; PACK(maxreal, 1023); - SYSTEM.GET(API.MainParam, argc) + SYSTEM.GET(API.MainParam, argc); + + libc := API.libc; + GetSym(libc, "fread", SYSTEM.ADR(fread)); + GetSym(libc, "fwrite", SYSTEM.ADR(fwrite)); + GetSym(libc, "fopen", SYSTEM.ADR(fopen)); + GetSym(libc, "fclose", SYSTEM.ADR(fclose)); + GetSym(libc, "chmod", SYSTEM.ADR(_chmod)); + GetSym(libc, "time", SYSTEM.ADR(time)); + GetSym(libc, "exit", SYSTEM.ADR(exit)); + GetSym(libc, "stdout", SYSTEM.ADR(stdout)); SYSTEM.GET(stdout - SYSTEM.SIZE(INTEGER), stdout); + + librt := API.dlopen(SYSTEM.SADR("librt.so.1"), RTLD_LAZY); + GetSym(librt, "clock_gettime", SYSTEM.ADR(clock_gettime)) END HOST. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux64/In.ob07 b/programs/develop/oberon07/Lib/Linux64/In.ob07 new file mode 100644 index 000000000..73fa891d0 --- /dev/null +++ b/programs/develop/oberon07/Lib/Linux64/In.ob07 @@ -0,0 +1,85 @@ +(* + BSD 2-Clause License + + Copyright (c) 2020, Anton Krotov + All rights reserved. +*) + +MODULE In; + +IMPORT SYSTEM, Libdl; + + +CONST + + MAX_LEN = 10240; + + +VAR + + Done*: BOOLEAN; + s: ARRAY MAX_LEN + 4 OF CHAR; + + sscanf: PROCEDURE [linux] (buf: INTEGER; fmt: INTEGER; adr: INTEGER): INTEGER; + gets: PROCEDURE [linux] (buf: INTEGER); + + +PROCEDURE String* (VAR str: ARRAY OF CHAR); +BEGIN + gets(SYSTEM.ADR(s[0])); + COPY(s, str); + str[LEN(str) - 1] := 0X; + Done := TRUE +END String; + + +PROCEDURE Int* (VAR x: INTEGER); +BEGIN + String(s); + Done := sscanf(SYSTEM.ADR(s[0]), SYSTEM.SADR("%lld"), SYSTEM.ADR(x)) = 1 +END Int; + + +PROCEDURE Real* (VAR x: REAL); +BEGIN + String(s); + Done := sscanf(SYSTEM.ADR(s[0]), SYSTEM.SADR("%lf"), SYSTEM.ADR(x)) = 1 +END Real; + + +PROCEDURE Char* (VAR x: CHAR); +BEGIN + String(s); + x := s[0] +END Char; + + +PROCEDURE Ln*; +BEGIN + String(s) +END Ln; + + +PROCEDURE Open*; +BEGIN + Done := TRUE +END Open; + + +PROCEDURE init; +VAR + libc: INTEGER; + +BEGIN + libc := Libdl.open("libc.so.6", Libdl.LAZY); + ASSERT(libc # 0); + SYSTEM.PUT(SYSTEM.ADR(sscanf), Libdl.sym(libc, "sscanf")); + ASSERT(sscanf # NIL); + SYSTEM.PUT(SYSTEM.ADR(gets), Libdl.sym(libc, "gets")); + ASSERT(gets # NIL); +END init; + + +BEGIN + init +END In. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux64/LINAPI.ob07 b/programs/develop/oberon07/Lib/Linux64/LINAPI.ob07 index c7931e231..98e601926 100644 --- a/programs/develop/oberon07/Lib/Linux64/LINAPI.ob07 +++ b/programs/develop/oberon07/Lib/Linux64/LINAPI.ob07 @@ -7,19 +7,17 @@ MODULE LINAPI; -IMPORT SYSTEM, API; +IMPORT SYSTEM, API, Libdl; TYPE - TP* = API.TP; - SOFINI* = API.SOFINI; + TP* = ARRAY 2 OF INTEGER; + SOFINI* = PROCEDURE; VAR - argc*, envc*: INTEGER; - libc*, librt*: INTEGER; stdout*, @@ -39,79 +37,44 @@ VAR clock_gettime* : PROCEDURE [linux] (clock_id: INTEGER; VAR tp: TP): INTEGER; -PROCEDURE GetArg* (n: INTEGER; VAR s: ARRAY OF CHAR); -VAR - i, len, ptr: INTEGER; - c: CHAR; - -BEGIN - i := 0; - len := LEN(s) - 1; - IF (0 <= n) & (n <= argc + envc) & (n # argc) & (len > 0) THEN - SYSTEM.GET(API.MainParam + (n + 1) * SYSTEM.SIZE(INTEGER), ptr); - REPEAT - SYSTEM.GET(ptr, c); - s[i] := c; - INC(i); - INC(ptr) - UNTIL (c = 0X) OR (i = len) - END; - s[i] := 0X -END GetArg; - - -PROCEDURE GetEnv* (n: INTEGER; VAR s: ARRAY OF CHAR); -BEGIN - IF (0 <= n) & (n < envc) THEN - GetArg(n + argc + 1, s) - ELSE - s[0] := 0X - END -END GetEnv; - - PROCEDURE SetFini* (ProcFini: SOFINI); BEGIN API.SetFini(ProcFini) END SetFini; -PROCEDURE init; +PROCEDURE GetSym (lib: INTEGER; name: ARRAY OF CHAR; VarAdr: INTEGER); VAR - ptr: INTEGER; + sym: INTEGER; BEGIN - IF API.MainParam # 0 THEN - envc := -1; - SYSTEM.GET(API.MainParam, argc); - REPEAT - SYSTEM.GET(API.MainParam + (envc + argc + 3) * SYSTEM.SIZE(INTEGER), ptr); - INC(envc) - UNTIL ptr = 0 - ELSE - envc := 0; - argc := 0 - END; + sym := Libdl.sym(lib, name); + ASSERT(sym # 0); + SYSTEM.PUT(VarAdr, sym) +END GetSym; + +PROCEDURE init; +BEGIN libc := API.libc; - stdout := API.stdout; - stdin := API.stdin; - stderr := API.stderr; + GetSym(libc, "exit", SYSTEM.ADR(exit)); + GetSym(libc, "puts", SYSTEM.ADR(puts)); + GetSym(libc, "malloc", SYSTEM.ADR(malloc)); + GetSym(libc, "free", SYSTEM.ADR(free)); + GetSym(libc, "fread", SYSTEM.ADR(fread)); + GetSym(libc, "fwrite", SYSTEM.ADR(fwrite)); + GetSym(libc, "fopen", SYSTEM.ADR(fopen)); + GetSym(libc, "fclose", SYSTEM.ADR(fclose)); + GetSym(libc, "time", SYSTEM.ADR(time)); - malloc := API.malloc; - free := API.free; - exit := API._exit; - puts := API.puts; - fwrite := API.fwrite; - fread := API.fread; - fopen := API.fopen; - fclose := API.fclose; - time := API.time; + GetSym(libc, "stdout", SYSTEM.ADR(stdout)); SYSTEM.GET(stdout - SYSTEM.SIZE(INTEGER), stdout); + GetSym(libc, "stdin", SYSTEM.ADR(stdin)); SYSTEM.GET(stdin - SYSTEM.SIZE(INTEGER), stdin); + GetSym(libc, "stderr", SYSTEM.ADR(stderr)); SYSTEM.GET(stderr - SYSTEM.SIZE(INTEGER), stderr); - librt := API.librt; + librt := Libdl.open("librt.so.1", Libdl.LAZY); - clock_gettime := API.clock_gettime + GetSym(librt, "clock_gettime", SYSTEM.ADR(clock_gettime)) END init; diff --git a/programs/develop/oberon07/Lib/Linux64/Math.ob07 b/programs/develop/oberon07/Lib/Linux64/Math.ob07 index ab80d79eb..42a5de5e7 100644 --- a/programs/develop/oberon07/Lib/Linux64/Math.ob07 +++ b/programs/develop/oberon07/Lib/Linux64/Math.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2019, Anton Krotov + Copyright (c) 2019-2020, Anton Krotov All rights reserved. *) @@ -12,22 +12,32 @@ IMPORT SYSTEM; CONST - e *= 2.71828182845904523; - pi *= 3.14159265358979324; - ln2 *= 0.693147180559945309; + pi* = 3.1415926535897932384626433832795028841972E0; + e* = 2.7182818284590452353602874713526624977572E0; - eps = 1.0E-16; - MaxCosArg = 1000000.0 * pi; + ZERO = 0.0E0; + ONE = 1.0E0; + HALF = 0.5E0; + TWO = 2.0E0; + sqrtHalf = 0.70710678118654752440E0; + eps = 5.5511151E-17; + ln2Inv = 1.44269504088896340735992468100189213E0; + piInv = ONE / pi; + Limit = 1.0536712E-8; + piByTwo = pi / TWO; + + expoMax = 1023; + expoMin = 1 - expoMax; VAR - Exp: ARRAY 710 OF REAL; + LnInfinity, LnSmall, large, miny: REAL; PROCEDURE [stdcall64] sqrt* (x: REAL): REAL; BEGIN - ASSERT(x >= 0.0); + ASSERT(x >= ZERO); SYSTEM.CODE( 0F2H, 0FH, 51H, 45H, 10H, (* sqrtsd xmm0, qword[rbp + 10h] *) 05DH, (* pop rbp *) @@ -38,205 +48,340 @@ BEGIN END sqrt; +PROCEDURE sqri* (x: INTEGER): INTEGER; + RETURN x * x +END sqri; + + +PROCEDURE sqrr* (x: REAL): REAL; + RETURN x * x +END sqrr; + + PROCEDURE exp* (x: REAL): REAL; CONST - e25 = 1.284025416687741484; (* exp(0.25) *) + c1 = 0.693359375E0; + c2 = -2.1219444005469058277E-4; + P0 = 0.249999999999999993E+0; + P1 = 0.694360001511792852E-2; + P2 = 0.165203300268279130E-4; + Q1 = 0.555538666969001188E-1; + Q2 = 0.495862884905441294E-3; VAR - a, s, res: REAL; - neg: BOOLEAN; + xn, g, p, q, z: REAL; n: INTEGER; BEGIN - neg := x < 0.0; - IF neg THEN - x := -x - END; - - IF x < FLT(LEN(Exp)) THEN - res := Exp[FLOOR(x)]; - x := x - FLT(FLOOR(x)); - WHILE x >= 0.25 DO - res := res * e25; - x := x - 0.25 - END + IF x > LnInfinity THEN + x := SYSTEM.INF() + ELSIF x < LnSmall THEN + x := ZERO + ELSIF ABS(x) < eps THEN + x := ONE ELSE - res := SYSTEM.INF(); - x := 0.0 - END; + IF x >= ZERO THEN + n := FLOOR(ln2Inv * x + HALF) + ELSE + n := FLOOR(ln2Inv * x - HALF) + END; - n := 0; - a := 1.0; - s := 1.0; - - REPEAT - INC(n); - a := a * x / FLT(n); - s := s + a - UNTIL a < eps; - - IF neg THEN - res := 1.0 / (res * s) - ELSE - res := res * s + xn := FLT(n); + g := (x - xn * c1) - xn * c2; + z := g * g; + p := ((P2 * z + P1) * z + P0) * g; + q := (Q2 * z + Q1) * z + HALF; + x := HALF + p / (q - p); + PACK(x, n + 1) END - RETURN res + RETURN x END exp; PROCEDURE ln* (x: REAL): REAL; +CONST + c1 = 355.0E0 / 512.0E0; + c2 = -2.121944400546905827679E-4; + P0 = -0.64124943423745581147E+2; + P1 = 0.16383943563021534222E+2; + P2 = -0.78956112887491257267E+0; + Q0 = -0.76949932108494879777E+3; + Q1 = 0.31203222091924532844E+3; + Q2 = -0.35667977739034646171E+2; + VAR - a, x2, res: REAL; + zn, zd, r, z, w, p, q, xn: REAL; n: INTEGER; BEGIN - ASSERT(x > 0.0); + ASSERT(x > ZERO); + UNPK(x, n); + x := x * HALF; - x := (x - 1.0) / (x + 1.0); - x2 := x * x; - res := x + FLT(n) * (ln2 * 0.5); - n := 1; + IF x > sqrtHalf THEN + zn := x - ONE; + zd := x * HALF + HALF; + INC(n) + ELSE + zn := x - HALF; + zd := zn * HALF + HALF + END; - REPEAT - INC(n, 2); - x := x * x2; - a := x / FLT(n); - res := res + a - UNTIL a < eps + z := zn / zd; + w := z * z; + q := ((w + Q2) * w + Q1) * w + Q0; + p := w * ((P2 * w + P1) * w + P0); + r := z + z * (p / q); + xn := FLT(n) - RETURN res * 2.0 + RETURN (xn * c2 + r) + xn * c1 END ln; PROCEDURE power* (base, exponent: REAL): REAL; BEGIN - ASSERT(base > 0.0) + ASSERT(base > ZERO) RETURN exp(exponent * ln(base)) END power; +PROCEDURE ipower* (base: REAL; exponent: INTEGER): REAL; +VAR + i: INTEGER; + a: REAL; + +BEGIN + a := 1.0; + + IF base # 0.0 THEN + IF exponent # 0 THEN + IF exponent < 0 THEN + base := 1.0 / base + END; + i := ABS(exponent); + WHILE i > 0 DO + WHILE ~ODD(i) DO + i := LSR(i, 1); + base := sqrr(base) + END; + DEC(i); + a := a * base + END + ELSE + a := 1.0 + END + ELSE + ASSERT(exponent > 0); + a := 0.0 + END + + RETURN a +END ipower; + + PROCEDURE log* (base, x: REAL): REAL; BEGIN - ASSERT(base > 0.0); - ASSERT(x > 0.0) + ASSERT(base > ZERO); + ASSERT(x > ZERO) RETURN ln(x) / ln(base) END log; -PROCEDURE cos* (x: REAL): REAL; +PROCEDURE SinCos (x, y, sign: REAL): REAL; +CONST + ymax = 210828714; + c1 = 3.1416015625E0; + c2 = -8.908910206761537356617E-6; + r1 = -0.16666666666666665052E+0; + r2 = 0.83333333333331650314E-2; + r3 = -0.19841269841201840457E-3; + r4 = 0.27557319210152756119E-5; + r5 = -0.25052106798274584544E-7; + r6 = 0.16058936490371589114E-9; + r7 = -0.76429178068910467734E-12; + r8 = 0.27204790957888846175E-14; + VAR - a, res: REAL; n: INTEGER; + xn, f, x1, g: REAL; BEGIN + ASSERT(y < FLT(ymax)); + + n := FLOOR(y * piInv + HALF); + xn := FLT(n); + IF ODD(n) THEN + sign := -sign + END; x := ABS(x); - ASSERT(x <= MaxCosArg); + IF x # y THEN + xn := xn - HALF + END; - x := x - FLT( FLOOR(x / (2.0 * pi)) ) * (2.0 * pi); - x := x * x; - res := 0.0; - a := 1.0; - n := -1; + x1 := FLT(FLOOR(x)); + f := ((x1 - xn * c1) + (x - x1)) - xn * c2; - REPEAT - INC(n, 2); - res := res + a; - a := -a * x / FLT(n*n + n) - UNTIL ABS(a) < eps + IF ABS(f) < Limit THEN + x := sign * f + ELSE + g := f * f; + g := (((((((r8 * g + r7) * g + r6) * g + r5) * g + r4) * g + r3) * g + r2) * g + r1) * g; + g := f + f * g; + x := sign * g + END - RETURN res -END cos; + RETURN x +END SinCos; PROCEDURE sin* (x: REAL): REAL; BEGIN - ASSERT(ABS(x) <= MaxCosArg); - x := cos(x) - RETURN sqrt(1.0 - x * x) -END sin; - - -PROCEDURE tan* (x: REAL): REAL; -BEGIN - ASSERT(ABS(x) <= MaxCosArg); - x := cos(x) - RETURN sqrt(1.0 - x * x) / x -END tan; - - -PROCEDURE arcsin* (x: REAL): REAL; - - - PROCEDURE arctan (x: REAL): REAL; - VAR - z, p, k: REAL; - - BEGIN - p := x / (x * x + 1.0); - z := p * x; - x := 0.0; - k := 0.0; - - REPEAT - k := k + 2.0; - x := x + p; - p := p * k * z / (k + 1.0) - UNTIL p < eps - - RETURN x - END arctan; - - -BEGIN - ASSERT(ABS(x) <= 1.0); - - IF ABS(x) >= 0.707 THEN - x := 0.5 * pi - arctan(sqrt(1.0 - x * x) / x) + IF x < ZERO THEN + x := SinCos(x, -x, -ONE) ELSE - x := arctan(x / sqrt(1.0 - x * x)) + x := SinCos(x, x, ONE) END RETURN x +END sin; + + +PROCEDURE cos* (x: REAL): REAL; + RETURN SinCos(x, ABS(x) + piByTwo, ONE) +END cos; + + +PROCEDURE tan* (x: REAL): REAL; +VAR + s, c: REAL; + +BEGIN + s := sin(x); + c := sqrt(ONE - s * s); + x := ABS(x) / (TWO * pi); + x := x - FLT(FLOOR(x)); + IF (0.25 < x) & (x < 0.75) THEN + c := -c + END + + RETURN s / c +END tan; + + +PROCEDURE arctan2* (y, x: REAL): REAL; +CONST + P0 = 0.216062307897242551884E+3; P1 = 0.3226620700132512059245E+3; + P2 = 0.13270239816397674701E+3; P3 = 0.1288838303415727934E+2; + Q0 = 0.2160623078972426128957E+3; Q1 = 0.3946828393122829592162E+3; + Q2 = 0.221050883028417680623E+3; Q3 = 0.3850148650835119501E+2; + Sqrt3 = 1.7320508075688772935E0; + +VAR + atan, z, z2, p, q: REAL; + yExp, xExp, Quadrant: INTEGER; + +BEGIN + IF ABS(x) < miny THEN + ASSERT(ABS(y) >= miny); + atan := piByTwo + ELSE + z := y; + UNPK(z, yExp); + z := x; + UNPK(z, xExp); + + IF yExp - xExp >= expoMax - 3 THEN + atan := piByTwo + ELSIF yExp - xExp < expoMin + 3 THEN + atan := ZERO + ELSE + IF ABS(y) > ABS(x) THEN + z := ABS(x / y); + Quadrant := 2 + ELSE + z := ABS(y / x); + Quadrant := 0 + END; + + IF z > TWO - Sqrt3 THEN + z := (z * Sqrt3 - ONE) / (Sqrt3 + z); + INC(Quadrant) + END; + + IF ABS(z) < Limit THEN + atan := z + ELSE + z2 := z * z; + p := (((P3 * z2 + P2) * z2 + P1) * z2 + P0) * z; + q := (((z2 + Q3) * z2 + Q2) * z2 + Q1) * z2 + Q0; + atan := p / q + END; + + CASE Quadrant OF + |0: + |1: atan := atan + pi / 6.0 + |2: atan := piByTwo - atan + |3: atan := pi / 3.0 - atan + END + END; + + IF x < ZERO THEN + atan := pi - atan + END + END; + + IF y < ZERO THEN + atan := -atan + END + + RETURN atan +END arctan2; + + +PROCEDURE arcsin* (x: REAL): REAL; +BEGIN + ASSERT(ABS(x) <= ONE) + RETURN arctan2(x, sqrt(ONE - x * x)) END arcsin; PROCEDURE arccos* (x: REAL): REAL; BEGIN - ASSERT(ABS(x) <= 1.0) - RETURN 0.5 * pi - arcsin(x) + ASSERT(ABS(x) <= ONE) + RETURN arctan2(sqrt(ONE - x * x), x) END arccos; PROCEDURE arctan* (x: REAL): REAL; - RETURN arcsin(x / sqrt(1.0 + x * x)) + RETURN arctan2(x, ONE) END arctan; PROCEDURE sinh* (x: REAL): REAL; BEGIN x := exp(x) - RETURN (x - 1.0 / x) * 0.5 + RETURN (x - ONE / x) * HALF END sinh; PROCEDURE cosh* (x: REAL): REAL; BEGIN x := exp(x) - RETURN (x + 1.0 / x) * 0.5 + RETURN (x + ONE / x) * HALF END cosh; PROCEDURE tanh* (x: REAL): REAL; BEGIN IF x > 15.0 THEN - x := 1.0 + x := ONE ELSIF x < -15.0 THEN - x := -1.0 + x := -ONE ELSE - x := exp(2.0 * x); - x := (x - 1.0) / (x + 1.0) + x := exp(TWO * x); + x := (x - ONE) / (x + ONE) END RETURN x @@ -244,21 +389,21 @@ END tanh; PROCEDURE arsinh* (x: REAL): REAL; - RETURN ln(x + sqrt(x * x + 1.0)) + RETURN ln(x + sqrt(x * x + ONE)) END arsinh; PROCEDURE arcosh* (x: REAL): REAL; BEGIN - ASSERT(x >= 1.0) - RETURN ln(x + sqrt(x * x - 1.0)) + ASSERT(x >= ONE) + RETURN ln(x + sqrt(x * x - ONE)) END arcosh; PROCEDURE artanh* (x: REAL): REAL; BEGIN - ASSERT(ABS(x) < 1.0) - RETURN 0.5 * ln((1.0 + x) / (1.0 - x)) + ASSERT(ABS(x) < ONE) + RETURN HALF * ln((ONE + x) / (ONE - x)) END artanh; @@ -267,9 +412,9 @@ VAR res: INTEGER; BEGIN - IF x > 0.0 THEN + IF x > ZERO THEN res := 1 - ELSIF x < 0.0 THEN + ELSIF x < ZERO THEN res := -1 ELSE res := 0 @@ -284,7 +429,7 @@ VAR res: REAL; BEGIN - res := 1.0; + res := ONE; WHILE n > 1 DO res := res * FLT(n); DEC(n) @@ -294,18 +439,42 @@ BEGIN END fact; -PROCEDURE init; +PROCEDURE DegToRad* (x: REAL): REAL; + RETURN x * (pi / 180.0) +END DegToRad; + + +PROCEDURE RadToDeg* (x: REAL): REAL; + RETURN x * (180.0 / pi) +END RadToDeg; + + +(* Return hypotenuse of triangle *) +PROCEDURE hypot* (x, y: REAL): REAL; VAR - i: INTEGER; + a: REAL; BEGIN - Exp[0] := 1.0; - FOR i := 1 TO LEN(Exp) - 1 DO - Exp[i] := Exp[i - 1] * e + x := ABS(x); + y := ABS(y); + IF x > y THEN + a := x * sqrt(1.0 + sqrr(y / x)) + ELSE + IF x > 0.0 THEN + a := y * sqrt(1.0 + sqrr(x / y)) + ELSE + a := y + END END -END init; + + RETURN a +END hypot; BEGIN - init + large := 1.9; + PACK(large, expoMax); + miny := ONE / large; + LnInfinity := ln(large); + LnSmall := ln(miny); END Math. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux64/Out.ob07 b/programs/develop/oberon07/Lib/Linux64/Out.ob07 index 48d4e84c6..6876dd4cd 100644 --- a/programs/develop/oberon07/Lib/Linux64/Out.ob07 +++ b/programs/develop/oberon07/Lib/Linux64/Out.ob07 @@ -1,276 +1,87 @@ (* - Copyright 2013, 2014, 2017, 2018, 2019 Anton Krotov + BSD 2-Clause License - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . + Copyright (c) 2020, Anton Krotov + All rights reserved. *) MODULE Out; -IMPORT sys := SYSTEM, API; +IMPORT SYSTEM, Libdl; -CONST - - d = 1.0 - 5.0E-12; VAR - Realp: PROCEDURE (x: REAL; width: INTEGER); + printf1: PROCEDURE [linux] (fmt: INTEGER; x: INTEGER); + printf2: PROCEDURE [linux] (fmt: INTEGER; width, x: INTEGER); + printf3: PROCEDURE [linux] (fmt: INTEGER; width, precision, x: INTEGER); -PROCEDURE Char*(x: CHAR); +PROCEDURE Char* (x: CHAR); BEGIN - API.putc(x) + printf1(SYSTEM.SADR("%c"), ORD(x)) END Char; -PROCEDURE String*(s: ARRAY OF CHAR); +PROCEDURE String* (s: ARRAY OF CHAR); +BEGIN + printf2(SYSTEM.SADR("%.*s"), LENGTH(s), SYSTEM.ADR(s[0])) +END String; + + +PROCEDURE Ln*; +BEGIN + printf1(SYSTEM.SADR("%s"), SYSTEM.SADR(0AX)) +END Ln; + + +PROCEDURE Int* (x, width: INTEGER); +BEGIN + printf2(SYSTEM.SADR("%*lld"), width, x) +END Int; + + +PROCEDURE intval (x: REAL): INTEGER; VAR i: INTEGER; BEGIN - i := 0; - WHILE (i < LEN(s)) & (s[i] # 0X) DO - Char(s[i]); - INC(i) - END -END String; + SYSTEM.GET(SYSTEM.ADR(x), i) + RETURN i +END intval; -PROCEDURE WriteInt(x, n: INTEGER); -VAR i: INTEGER; a: ARRAY 24 OF CHAR; neg: BOOLEAN; +PROCEDURE Real* (x: REAL; width: INTEGER); BEGIN - i := 0; - IF n < 1 THEN - n := 1 - END; - IF x < 0 THEN - x := -x; - DEC(n); - neg := TRUE - END; - REPEAT - a[i] := CHR(x MOD 10 + ORD("0")); - x := x DIV 10; - INC(i) - UNTIL x = 0; - WHILE n > i DO - Char(" "); - DEC(n) - END; - IF neg THEN - Char("-") - END; - REPEAT - DEC(i); - Char(a[i]) - UNTIL i = 0 -END WriteInt; - -PROCEDURE IsNan(AValue: REAL): BOOLEAN; -VAR s: SET; -BEGIN - sys.GET(sys.ADR(AValue), s) - RETURN (s * {52..62} = {52..62}) & ((s * {32..51} # {}) OR (s * {0..31} # {})) -END IsNan; - -PROCEDURE IsInf(x: REAL): BOOLEAN; - RETURN ABS(x) = sys.INF() -END IsInf; - -PROCEDURE Int*(x, width: INTEGER); -VAR i: INTEGER; -BEGIN - IF x # 80000000H THEN - WriteInt(x, width) - ELSE - FOR i := 12 TO width DO - Char(20X) - END; - String("-2147483648") - END -END Int; - -PROCEDURE OutInf(x: REAL; width: INTEGER); -VAR s: ARRAY 5 OF CHAR; i: INTEGER; -BEGIN - IF IsNan(x) THEN - s := "Nan"; - INC(width) - ELSIF IsInf(x) & (x > 0.0) THEN - s := "+Inf" - ELSIF IsInf(x) & (x < 0.0) THEN - s := "-Inf" - END; - FOR i := 1 TO width - 4 DO - Char(" ") - END; - String(s) -END OutInf; - -PROCEDURE Ln*; -BEGIN - Char(0AX) -END Ln; - -PROCEDURE _FixReal(x: REAL; width, p: INTEGER); -VAR e, len, i: INTEGER; y: REAL; minus: BOOLEAN; -BEGIN - IF IsNan(x) OR IsInf(x) THEN - OutInf(x, width) - ELSIF p < 0 THEN - Realp(x, width) - ELSE - len := 0; - minus := FALSE; - IF x < 0.0 THEN - minus := TRUE; - INC(len); - x := ABS(x) - END; - e := 0; - WHILE x >= 10.0 DO - x := x / 10.0; - INC(e) - END; - - IF e >= 0 THEN - len := len + e + p + 1; - IF x > 9.0 + d THEN - INC(len) - END; - IF p > 0 THEN - INC(len) - END; - ELSE - len := len + p + 2 - END; - FOR i := 1 TO width - len DO - Char(" ") - END; - IF minus THEN - Char("-") - END; - y := x; - WHILE (y < 1.0) & (y # 0.0) DO - y := y * 10.0; - DEC(e) - END; - IF e < 0 THEN - IF x - FLT(FLOOR(x)) > d THEN - Char("1"); - x := 0.0 - ELSE - Char("0"); - x := x * 10.0 - END - ELSE - WHILE e >= 0 DO - IF x - FLT(FLOOR(x)) > d THEN - IF x > 9.0 THEN - String("10") - ELSE - Char(CHR(FLOOR(x) + ORD("0") + 1)) - END; - x := 0.0 - ELSE - Char(CHR(FLOOR(x) + ORD("0"))); - x := (x - FLT(FLOOR(x))) * 10.0 - END; - DEC(e) - END - END; - IF p > 0 THEN - Char(".") - END; - WHILE p > 0 DO - IF x - FLT(FLOOR(x)) > d THEN - Char(CHR(FLOOR(x) + ORD("0") + 1)); - x := 0.0 - ELSE - Char(CHR(FLOOR(x) + ORD("0"))); - x := (x - FLT(FLOOR(x))) * 10.0 - END; - DEC(p) - END - END -END _FixReal; - -PROCEDURE Real*(x: REAL; width: INTEGER); -VAR e, n, i: INTEGER; minus: BOOLEAN; -BEGIN - Realp := Real; - IF IsNan(x) OR IsInf(x) THEN - OutInf(x, width) - ELSE - e := 0; - n := 0; - IF width > 23 THEN - n := width - 23; - width := 23 - ELSIF width < 9 THEN - width := 9 - END; - width := width - 5; - IF x < 0.0 THEN - x := -x; - minus := TRUE - ELSE - minus := FALSE - END; - WHILE x >= 10.0 DO - x := x / 10.0; - INC(e) - END; - WHILE (x < 1.0) & (x # 0.0) DO - x := x * 10.0; - DEC(e) - END; - IF x > 9.0 + d THEN - x := 1.0; - INC(e) - END; - FOR i := 1 TO n DO - Char(" ") - END; - IF minus THEN - x := -x - END; - _FixReal(x, width, width - 3); - Char("E"); - IF e >= 0 THEN - Char("+") - ELSE - Char("-"); - e := ABS(e) - END; - IF e < 100 THEN - Char("0") - END; - IF e < 10 THEN - Char("0") - END; - Int(e, 0) - END + printf3(SYSTEM.SADR("%*.*E"), width, MAX(MIN(width - 8, 15), 1), intval(x)) END Real; -PROCEDURE FixReal*(x: REAL; width, p: INTEGER); + +PROCEDURE FixReal* (x: REAL; width, precision: INTEGER); BEGIN - Realp := Real; - _FixReal(x, width, p) + printf3(SYSTEM.SADR("%*.*f"), width, precision, intval(x)) END FixReal; + PROCEDURE Open*; END Open; + +PROCEDURE init; +VAR + libc, printf: INTEGER; + +BEGIN + libc := Libdl.open("libc.so.6", Libdl.LAZY); + ASSERT(libc # 0); + printf := Libdl.sym(libc, "printf"); + ASSERT(printf # 0); + SYSTEM.PUT(SYSTEM.ADR(printf1), printf); + SYSTEM.PUT(SYSTEM.ADR(printf2), printf); + SYSTEM.PUT(SYSTEM.ADR(printf3), printf); +END init; + + +BEGIN + init END Out. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux64/RTL.ob07 b/programs/develop/oberon07/Lib/Linux64/RTL.ob07 index 94a94eafd..7b6bbfb6a 100644 --- a/programs/develop/oberon07/Lib/Linux64/RTL.ob07 +++ b/programs/develop/oberon07/Lib/Linux64/RTL.ob07 @@ -350,33 +350,29 @@ END PCharToStr; PROCEDURE IntToStr (x: INTEGER; VAR str: ARRAY OF CHAR); VAR - i, a, b: INTEGER; - c: CHAR; + i, a: INTEGER; BEGIN i := 0; + a := x; REPEAT - str[i] := CHR(x MOD 10 + ORD("0")); - x := x DIV 10; - INC(i) - UNTIL x = 0; + INC(i); + a := a DIV 10 + UNTIL a = 0; - a := 0; - b := i - 1; - WHILE a < b DO - c := str[a]; - str[a] := str[b]; - str[b] := c; - INC(a); - DEC(b) - END; - str[i] := 0X + str[i] := 0X; + + REPEAT + DEC(i); + str[i] := CHR(x MOD 10 + ORD("0")); + x := x DIV 10 + UNTIL x = 0 END IntToStr; PROCEDURE append (VAR s1: ARRAY OF CHAR; s2: ARRAY OF CHAR); VAR - n1, n2, i, j: INTEGER; + n1, n2: INTEGER; BEGIN n1 := LENGTH(s1); @@ -384,19 +380,12 @@ BEGIN ASSERT(n1 + n2 < LEN(s1)); - i := 0; - j := n1; - WHILE i < n2 DO - s1[j] := s2[i]; - INC(i); - INC(j) - END; - - s1[j] := 0X + SYSTEM.MOVE(SYSTEM.ADR(s2[0]), SYSTEM.ADR(s1[n1]), n2); + s1[n1 + n2] := 0X END append; -PROCEDURE [stdcall64] _error* (module, err, line: INTEGER); +PROCEDURE [stdcall64] _error* (modnum, _module, err, line: INTEGER); VAR s, temp: ARRAY 1024 OF CHAR; @@ -415,10 +404,8 @@ BEGIN |11: s := "BYTE out of range" END; - append(s, API.eol); - - append(s, "module: "); PCharToStr(module, temp); append(s, temp); append(s, API.eol); - append(s, "line: "); IntToStr(line, temp); append(s, temp); + append(s, API.eol + "module: "); PCharToStr(_module, temp); append(s, temp); + append(s, API.eol + "line: "); IntToStr(line, temp); append(s, temp); API.DebugMsg(SYSTEM.ADR(s[0]), name); diff --git a/programs/develop/oberon07/Lib/MSP430/MSP430.ob07 b/programs/develop/oberon07/Lib/MSP430/MSP430.ob07 new file mode 100644 index 000000000..8cf8169b6 --- /dev/null +++ b/programs/develop/oberon07/Lib/MSP430/MSP430.ob07 @@ -0,0 +1,125 @@ +(* + BSD 2-Clause License + + Copyright (c) 2019-2020, Anton Krotov + All rights reserved. +*) + +MODULE MSP430; + +IMPORT SYSTEM; + + +CONST + + iv = 0FFC0H; + + bsl = iv - 2; + sp = bsl - 2; + empty_proc = sp - 2; + free_size = empty_proc - 2; + free_adr = free_size - 2; + bits = free_adr - 272; + bits_offs = bits - 32; + types = bits_offs - 2; + + ram = 200H; + + trap = ram; + int = trap + 2; + + + GIE* = {3}; + CPUOFF* = {4}; + OSCOFF* = {5}; + SCG0* = {6}; + SCG1* = {7}; + + +TYPE + + TInterrupt* = RECORD priority*: INTEGER; sr*: SET; pc*: INTEGER END; + + TTrapProc* = PROCEDURE (modNum, modName, err, line: INTEGER); + + TIntProc* = PROCEDURE (priority: INTEGER; interrupt: TInterrupt); + + +PROCEDURE SetTrapProc* (TrapProc: TTrapProc); +BEGIN + SYSTEM.PUT(trap, TrapProc) +END SetTrapProc; + + +PROCEDURE SetIntProc* (IntProc: TIntProc); +BEGIN + SYSTEM.PUT(int, IntProc) +END SetIntProc; + + +PROCEDURE SetIntPC* (interrupt: TInterrupt; NewPC: INTEGER); +BEGIN + SYSTEM.PUT(SYSTEM.ADR(interrupt.pc), NewPC) +END SetIntPC; + + +PROCEDURE SetIntSR* (interrupt: TInterrupt; NewSR: SET); +BEGIN + SYSTEM.PUT(SYSTEM.ADR(interrupt.sr), NewSR) +END SetIntSR; + + +PROCEDURE [code] DInt* + 0C232H; (* BIC #8, SR *) + + +PROCEDURE [code] EInt* + 0D232H; (* BIS #8, SR *) + + +PROCEDURE [code] CpuOff* + 0D032H, 16; (* BIS #16, SR *) + + +PROCEDURE [code] Halt* + 4032H, 0F0H; (* MOV CPUOFF+OSCOFF+SCG0+SCG1, SR *) + + +PROCEDURE [code] Restart* + 4302H, (* MOV #0, SR *) + 4210H, 0FFFEH; (* MOV 0FFFEH(SR), PC *) + + +PROCEDURE [code] SetSR* (bits: SET) + 0D112H, 2; (* BIS 2(SP), SR *) + + +PROCEDURE [code] ClrSR* (bits: SET) + 0C112H, 2; (* BIC 2(SP), SR *) + + +PROCEDURE GetFreeFlash* (VAR address, size: INTEGER); +BEGIN + SYSTEM.GET(free_adr, address); + SYSTEM.GET(free_size, size) +END GetFreeFlash; + + +PROCEDURE [code] Delay* (n: INTEGER) + 4035H, 124, (* MOV #124, R5 *) + (* L2: *) + 4114H, 2, (* MOV 2(SP), R4 *) + 8324H, (* SUB #2, R4 *) + (* L1: *) + 4303H, (* NOP *) + 4303H, (* NOP *) + 4303H, (* NOP *) + 4303H, (* NOP *) + 4303H, (* NOP *) + 8314H, (* SUB #1, R4 *) + 3800H - 7, (* JGE L1 *) + 8315H, (* SUB #1, R5 *) + 3800H - 12; (* JGE L2 *) + + +END MSP430. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Math/CMath.ob07 b/programs/develop/oberon07/Lib/Math/CMath.ob07 new file mode 100644 index 000000000..e1d48b0b5 --- /dev/null +++ b/programs/develop/oberon07/Lib/Math/CMath.ob07 @@ -0,0 +1,462 @@ +(* *********************************************** + Модуль работы с комплексными числами. + Вадим Исаев, 2020 + Module for complex numbers. + Vadim Isaev, 2020 +*************************************************** *) + +MODULE CMath; + +IMPORT Math, Out; + +TYPE + complex* = POINTER TO RECORD + re*: REAL; + im*: REAL + END; + +VAR + result: complex; + + i* : complex; + _0*: complex; + +(* Инициализация комплексного числа. + Init complex number. *) +PROCEDURE CInit* (re : REAL; im: REAL): complex; +VAR + temp: complex; +BEGIN + NEW(temp); + temp.re:=re; + temp.im:=im; + + RETURN temp +END CInit; + + +(* Четыре основных арифметических операций. + Four base operations +, -, * , / *) + +(* Сложение + addition : z := z1 + z2 *) +PROCEDURE CAdd* (z1, z2: complex): complex; +BEGIN + result.re := z1.re + z2.re; + result.im := z1.im + z2.im; + + RETURN result +END CAdd; + +(* Сложение с REAL. + addition : z := z1 + r1 *) +PROCEDURE CAdd_r* (z1: complex; r1: REAL): complex; +BEGIN + result.re := z1.re + r1; + result.im := z1.im; + + RETURN result +END CAdd_r; + +(* Сложение с INTEGER. + addition : z := z1 + i1 *) +PROCEDURE CAdd_i* (z1: complex; i1: INTEGER): complex; +BEGIN + result.re := z1.re + FLT(i1); + result.im := z1.im; + + RETURN result +END CAdd_i; + +(* Смена знака. + substraction : z := - z1 *) +PROCEDURE CNeg (z1 : complex): complex; +BEGIN + result.re := -z1.re; + result.im := -z1.im; + + RETURN result +END CNeg; + +(* Вычитание. + substraction : z := z1 - z2 *) +PROCEDURE CSub* (z1, z2 : complex): complex; +BEGIN + result.re := z1.re - z2.re; + result.im := z1.im - z2.im; + + RETURN result +END CSub; + +(* Вычитание REAL. + substraction : z := z1 - r1 *) +PROCEDURE CSub_r1* (z1 : complex; r1 : REAL): complex; +BEGIN + result.re := z1.re - r1; + result.im := z1.im; + + RETURN result +END CSub_r1; + +(* Вычитание из REAL. + substraction : z := r1 - z1 *) +PROCEDURE CSub_r2* (r1 : REAL; z1 : complex): complex; +BEGIN + result.re := r1 - z1.re; + result.im := - z1.im; + + RETURN result +END CSub_r2; + +(* Вычитание INTEGER. + substraction : z := z1 - i1 *) +PROCEDURE CSub_i* (z1 : complex; i1 : INTEGER): complex; +BEGIN + result.re := z1.re - FLT(i1); + result.im := z1.im; + + RETURN result +END CSub_i; + +(* Умножение. + multiplication : z := z1 * z2 *) +PROCEDURE CMul (z1, z2 : complex): complex; +BEGIN + result.re := (z1.re * z2.re) - (z1.im * z2.im); + result.im := (z1.re * z2.im) + (z1.im * z2.re); + + RETURN result +END CMul; + +(* Умножение с REAL. + multiplication : z := z1 * r1 *) +PROCEDURE CMul_r (z1 : complex; r1 : REAL): complex; +BEGIN + result.re := z1.re * r1; + result.im := z1.im * r1; + + RETURN result +END CMul_r; + +(* Умножение с INTEGER. + multiplication : z := z1 * i1 *) +PROCEDURE CMul_i (z1 : complex; i1 : INTEGER): complex; +BEGIN + result.re := z1.re * FLT(i1); + result.im := z1.im * FLT(i1); + + RETURN result +END CMul_i; + +(* Деление. + division : z := znum / zden *) +PROCEDURE CDiv (z1, z2 : complex): complex; + (* The following algorithm is used to properly handle + denominator overflow: + + | a + b(d/c) c - a(d/c) + | ---------- + ---------- I if |d| < |c| + a + b I | c + d(d/c) a + d(d/c) + ------- = | + c + d I | b + a(c/d) -a+ b(c/d) + | ---------- + ---------- I if |d| >= |c| + | d + c(c/d) d + c(c/d) + *) +VAR + tmp, denom : REAL; +BEGIN + IF ( ABS(z2.re) > ABS(z2.im) ) THEN + tmp := z2.im / z2.re; + denom := z2.re + z2.im * tmp; + result.re := (z1.re + z1.im * tmp) / denom; + result.im := (z1.im - z1.re * tmp) / denom; + ELSE + tmp := z2.re / z2.im; + denom := z2.im + z2.re * tmp; + result.re := (z1.im + z1.re * tmp) / denom; + result.im := (-z1.re + z1.im * tmp) / denom; + END; + + RETURN result +END CDiv; + +(* Деление на REAL. + division : z := znum / r1 *) +PROCEDURE CDiv_r* (z1 : complex; r1 : REAL): complex; +BEGIN + result.re := z1.re / r1; + result.im := z1.im / r1; + + RETURN result +END CDiv_r; + +(* Деление на INTEGER. + division : z := znum / i1 *) +PROCEDURE CDiv_i* (z1 : complex; i1 : INTEGER): complex; +BEGIN + result.re := z1.re / FLT(i1); + result.im := z1.im / FLT(i1); + + RETURN result +END CDiv_i; + +(* fonctions elementaires *) + +(* Вывод на экран. + out complex number *) +PROCEDURE CPrint* (z: complex; width: INTEGER); +BEGIN + Out.Real(z.re, width); + IF z.im>=0.0 THEN + Out.String("+"); + END; + Out.Real(z.im, width); + Out.String("i"); +END CPrint; + +PROCEDURE CPrintLn* (z: complex; width: INTEGER); +BEGIN + CPrint(z, width); + Out.Ln; +END CPrintLn; + +(* Вывод на экран с фиксированным кол-вом знаков + после запятой (p) *) +PROCEDURE CPrintFix* (z: complex; width, p: INTEGER); +BEGIN + Out.FixReal(z.re, width, p); + IF z.im>=0.0 THEN + Out.String("+"); + END; + Out.FixReal(z.im, width, p); + Out.String("i"); +END CPrintFix; + +PROCEDURE CPrintFixLn* (z: complex; width, p: INTEGER); +BEGIN + CPrintFix(z, width, p); + Out.Ln; +END CPrintFixLn; + +(* Модуль числа. + module : r = |z| *) +PROCEDURE CMod* (z1 : complex): REAL; +BEGIN + RETURN Math.sqrt((z1.re * z1.re) + (z1.im * z1.im)) +END CMod; + +(* Квадрат числа. + square : r := z*z *) +PROCEDURE CSqr* (z1: complex): complex; +BEGIN + result.re := z1.re * z1.re - z1.im * z1.im; + result.im := 2.0 * z1.re * z1.im; + + RETURN result +END CSqr; + +(* Квадратный корень числа. + square root : r := sqrt(z) *) +PROCEDURE CSqrt* (z1: complex): complex; +VAR + root, q: REAL; +BEGIN + IF (z1.re#0.0) OR (z1.im#0.0) THEN + root := Math.sqrt(0.5 * (ABS(z1.re) + CMod(z1))); + q := z1.im / (2.0 * root); + IF z1.re >= 0.0 THEN + result.re := root; + result.im := q; + ELSE + IF z1.im < 0.0 THEN + result.re := - q; + result.im := - root + ELSE + result.re := q; + result.im := root + END + END + ELSE + result := z1; + END; + + RETURN result +END CSqrt; + +(* Экспонента. + exponantial : r := exp(z) *) +(* exp(x + iy) = exp(x).exp(iy) = exp(x).[cos(y) + i sin(y)] *) +PROCEDURE CExp* (z: complex): complex; +VAR + expz : REAL; +BEGIN + expz := Math.exp(z.re); + result.re := expz * Math.cos(z.im); + result.im := expz * Math.sin(z.im); + + RETURN result +END CExp; + +(* Натуральный логарифм. + natural logarithm : r := ln(z) *) +(* ln( p exp(i0)) = ln(p) + i0 + 2kpi *) +PROCEDURE CLn* (z: complex): complex; +BEGIN + result.re := Math.ln(CMod(z)); + result.im := Math.arctan2(z.im, z.re); + + RETURN result +END CLn; + +(* Число в степени. + exp : z := z1^z2 *) +PROCEDURE CPower* (z1, z2 : complex): complex; +VAR + a: complex; +BEGIN + a:=CLn(z1); + a:=CMul(z2, a); + result:=CExp(a); + + RETURN result +END CPower; + +(* Число в степени REAL. + multiplication : z := z1^r *) +PROCEDURE CPower_r* (z1: complex; r: REAL): complex; +VAR + a: complex; +BEGIN + a:=CLn(z1); + a:=CMul_r(a, r); + result:=CExp(a); + + RETURN result +END CPower_r; + +(* Обратное число. + inverse : r := 1 / z *) +PROCEDURE CInv* (z: complex): complex; +VAR + denom : REAL; +BEGIN + denom := (z.re * z.re) + (z.im * z.im); + (* generates a fpu exception if denom=0 as for reals *) + result.re:=z.re/denom; + result.im:=-z.im/denom; + + RETURN result +END CInv; + +(* direct trigonometric functions *) + +(* Косинус. + complex cosinus *) +(* cos(x+iy) = cos(x).cos(iy) - sin(x).sin(iy) *) +(* cos(ix) = cosh(x) et sin(ix) = i.sinh(x) *) +PROCEDURE CCos* (z: complex): complex; +BEGIN + result.re := Math.cos(z.re) * Math.cosh(z.im); + result.im := - Math.sin(z.re) * Math.sinh(z.im); + + RETURN result +END CCos; + +(* Синус. + sinus complex *) +(* sin(x+iy) = sin(x).cos(iy) + cos(x).sin(iy) *) +(* cos(ix) = cosh(x) et sin(ix) = i.sinh(x) *) +PROCEDURE CSin (z: complex): complex; +BEGIN + result.re := Math.sin(z.re) * Math.cosh(z.im); + result.im := Math.cos(z.re) * Math.sinh(z.im); + + RETURN result +END CSin; + +(* Тангенс. + tangente *) +PROCEDURE CTg* (z: complex): complex; +VAR + temp1, temp2: complex; +BEGIN + temp1:=CSin(z); + temp2:=CCos(z); + result:=CDiv(temp1, temp2); + + RETURN result +END CTg; + +(* inverse complex hyperbolic functions *) + +(* Гиперболический арккосинус. + hyberbolic arg cosinus *) +(* _________ *) +(* argch(z) = -/+ ln(z + i.V 1 - z.z) *) +PROCEDURE CArcCosh* (z : complex): complex; +BEGIN + result:=CNeg(CLn(CAdd(z, CMul(i, CSqrt(CSub_r2(1.0, CMul(z, z))))))); + + RETURN result +END CArcCosh; + +(* Гиперболический арксинус. + hyperbolic arc sinus *) +(* ________ *) +(* argsh(z) = ln(z + V 1 + z.z) *) +PROCEDURE CArcSinh* (z : complex): complex; +BEGIN + result:=CLn(CAdd(z, CSqrt(CAdd_r(CMul(z, z), 1.0)))); + + RETURN result +END CArcSinh; + +(* Гиперболический арктангенс. + hyperbolic arc tangent *) +(* argth(z) = 1/2 ln((z + 1) / (1 - z)) *) +PROCEDURE CArcTgh (z : complex): complex; +BEGIN + result:=CDiv_r(CLn(CDiv(CAdd_r(z, 1.0), CSub_r2(1.0, z))), 2.0); + + RETURN result +END CArcTgh; + +(* trigonometriques inverses *) + +(* Арккосинус. + arc cosinus complex *) +(* arccos(z) = -i.argch(z) *) +PROCEDURE CArcCos* (z: complex): complex; +BEGIN + result := CNeg(CMul(i, CArcCosh(z))); + + RETURN result +END CArcCos; + +(* Арксинус. + arc sinus complex *) +(* arcsin(z) = -i.argsh(i.z) *) +PROCEDURE CArcSin* (z : complex): complex; +BEGIN + result := CNeg(CMul(i, CArcSinh(z))); + + RETURN result +END CArcSin; + +(* Арктангенс. + arc tangente complex *) +(* arctg(z) = -i.argth(i.z) *) +PROCEDURE CArcTg* (z : complex): complex; +BEGIN + result := CNeg(CMul(i, CArcTgh(CMul(i, z)))); + + RETURN result +END CArcTg; + +BEGIN + + result:=CInit(0.0, 0.0); + i :=CInit(0.0, 1.0); + _0:=CInit(0.0, 0.0); + +END CMath. diff --git a/programs/develop/oberon07/Lib/Math/MathBits.ob07 b/programs/develop/oberon07/Lib/Math/MathBits.ob07 new file mode 100644 index 000000000..3d102c226 --- /dev/null +++ b/programs/develop/oberon07/Lib/Math/MathBits.ob07 @@ -0,0 +1,33 @@ +(* **************************************** + Дополнение к модулю Math. + Побитовые операции над целыми числами. + Вадим Исаев, 2020 + Additional functions to the module Math. + Bitwise operations on integers. + Vadim Isaev, 2020 +******************************************* *) + +MODULE MathBits; + + +PROCEDURE iand* (x, y: INTEGER): INTEGER; + RETURN ORD(BITS(x) * BITS(y)) +END iand; + + +PROCEDURE ior* (x, y: INTEGER): INTEGER; + RETURN ORD(BITS(x) + BITS(y)) +END ior; + + +PROCEDURE ixor* (x, y: INTEGER): INTEGER; + RETURN ORD(BITS(x) / BITS(y)) +END ixor; + + +PROCEDURE inot* (x: INTEGER): INTEGER; + RETURN ORD(-BITS(x)) +END inot; + + +END MathBits. diff --git a/programs/develop/oberon07/Lib/Math/MathRound.ob07 b/programs/develop/oberon07/Lib/Math/MathRound.ob07 new file mode 100644 index 000000000..ac2548a02 --- /dev/null +++ b/programs/develop/oberon07/Lib/Math/MathRound.ob07 @@ -0,0 +1,99 @@ +(* ****************************************** + Дополнительные функции к модулю Math. + Функции округления. + Вадим Исаев, 2020 + ------------------------------------- + Additional functions to the module Math. + Rounding functions. + Vadim Isaev, 2020 +********************************************* *) + +MODULE MathRound; + +IMPORT Math; + + +(* Возвращается целая часть числа x. + Returns the integer part of a argument x.*) +PROCEDURE trunc* (x: REAL): REAL; +VAR + a: REAL; + +BEGIN + a := FLT(FLOOR(x)); + IF (x < 0.0) & (x # a) THEN + a := a + 1.0 + END + + RETURN a +END trunc; + + +(* Возвращается дробная часть числа x. + Returns the fractional part of the argument x *) +PROCEDURE frac* (x: REAL): REAL; + RETURN x - trunc(x) +END frac; + + +(* Округление к ближайшему целому. + Rounding to the nearest integer. *) +PROCEDURE round* (x: REAL): REAL; +VAR + a: REAL; + +BEGIN + a := trunc(x); + IF ABS(frac(x)) >= 0.5 THEN + a := a + FLT(Math.sgn(x)) + END + + RETURN a +END round; + + +(* Округление к бОльшему целому. + Rounding to a largest integer *) +PROCEDURE ceil* (x: REAL): REAL; +VAR + a: REAL; + +BEGIN + a := FLT(FLOOR(x)); + IF x # a THEN + a := a + 1.0 + END + + RETURN a +END ceil; + + +(* Округление к меньшему целому. + Rounding to a smallest integer *) +PROCEDURE floor* (x: REAL): REAL; + RETURN FLT(FLOOR(x)) +END floor; + + +(* Округление до определённого количества знаков: + - если Digits отрицательное, то округление + в знаках после десятичной запятой; + - если Digits положительное, то округление + в знаках до запятой *) +PROCEDURE SimpleRoundTo* (AValue: REAL; Digits: INTEGER): REAL; +VAR + RV, a : REAL; + +BEGIN + RV := Math.ipower(10.0, -Digits); + IF AValue < 0.0 THEN + a := trunc((AValue * RV) - 0.5) + ELSE + a := trunc((AValue * RV) + 0.5) + END + + RETURN a / RV +END SimpleRoundTo; + + +END MathRound. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Math/MathStat.ob07 b/programs/develop/oberon07/Lib/Math/MathStat.ob07 new file mode 100644 index 000000000..a05d14476 --- /dev/null +++ b/programs/develop/oberon07/Lib/Math/MathStat.ob07 @@ -0,0 +1,238 @@ +(* ******************************************** + Дополнение к модулю Math. + Статистические процедуры. + ------------------------------------- + Additional functions to the module Math. + Statistical functions +*********************************************** *) + +MODULE MathStat; + +IMPORT Math; + + +(*Минимальное значение. Нецелое *) +PROCEDURE MinValue* (data: ARRAY OF REAL; N: INTEGER): REAL; +VAR + i: INTEGER; + a: REAL; + +BEGIN + a := data[0]; + FOR i := 1 TO N - 1 DO + IF data[i] < a THEN + a := data[i] + END + END + + RETURN a +END MinValue; + + +(*Минимальное значение. Целое *) +PROCEDURE MinIntValue* (data: ARRAY OF INTEGER; N: INTEGER): INTEGER; +VAR + i: INTEGER; + a: INTEGER; + +BEGIN + a := data[0]; + FOR i := 1 TO N - 1 DO + IF data[i] < a THEN + a := data[i] + END + END + + RETURN a +END MinIntValue; + + +(*Максимальное значение. Нецелое *) +PROCEDURE MaxValue* (data: ARRAY OF REAL; N: INTEGER): REAL; +VAR + i: INTEGER; + a: REAL; + +BEGIN + a := data[0]; + FOR i := 1 TO N - 1 DO + IF data[i] > a THEN + a := data[i] + END + END + + RETURN a +END MaxValue; + + +(*Максимальное значение. Целое *) +PROCEDURE MaxIntValue* (data: ARRAY OF INTEGER; N: INTEGER): INTEGER; +VAR + i: INTEGER; + a: INTEGER; + +BEGIN + a := data[0]; + FOR i := 1 TO N - 1 DO + IF data[i] > a THEN + a := data[i] + END + END + + RETURN a +END MaxIntValue; + + +(* Сумма значений массива *) +PROCEDURE Sum* (data: ARRAY OF REAL; Count: INTEGER): REAL; +VAR + a: REAL; + i: INTEGER; + +BEGIN + a := 0.0; + FOR i := 0 TO Count - 1 DO + a := a + data[i] + END + + RETURN a +END Sum; + + +(* Сумма целых значений массива *) +PROCEDURE SumInt* (data: ARRAY OF INTEGER; Count: INTEGER): INTEGER; +VAR + a: INTEGER; + i: INTEGER; + +BEGIN + a := 0; + FOR i := 0 TO Count - 1 DO + a := a + data[i] + END + + RETURN a +END SumInt; + + +(* Сумма квадратов значений массива *) +PROCEDURE SumOfSquares* (data : ARRAY OF REAL; Count: INTEGER): REAL; +VAR + a: REAL; + i: INTEGER; + +BEGIN + a := 0.0; + FOR i := 0 TO Count - 1 DO + a := a + Math.sqrr(data[i]) + END + + RETURN a +END SumOfSquares; + + +(* Сумма значений и сумма квадратов значений массмва *) +PROCEDURE SumsAndSquares* (data: ARRAY OF REAL; Count : INTEGER; + VAR sum, sumofsquares : REAL); +VAR + i: INTEGER; + temp: REAL; + +BEGIN + sumofsquares := 0.0; + sum := 0.0; + FOR i := 0 TO Count - 1 DO + temp := data[i]; + sumofsquares := sumofsquares + Math.sqrr(temp); + sum := sum + temp + END +END SumsAndSquares; + + +(* Средниее значений массива *) +PROCEDURE Mean* (data: ARRAY OF REAL; Count: INTEGER): REAL; + RETURN Sum(data, Count) / FLT(Count) +END Mean; + + +PROCEDURE MeanAndTotalVariance* (data: ARRAY OF REAL; Count: INTEGER; + VAR mu: REAL; VAR variance: REAL); +VAR + i: INTEGER; + +BEGIN + mu := Mean(data, Count); + variance := 0.0; + FOR i := 0 TO Count - 1 DO + variance := variance + Math.sqrr(data[i] - mu) + END +END MeanAndTotalVariance; + + +(* Вычисление статистической дисперсии равной сумме квадратов разницы + между каждым конкретным значением массива Data и средним значением *) +PROCEDURE TotalVariance* (data: ARRAY OF REAL; Count: INTEGER): REAL; +VAR + mu, tv: REAL; + +BEGIN + MeanAndTotalVariance(data, Count, mu, tv) + RETURN tv +END TotalVariance; + + +(* Типовая дисперсия всех значений массива *) +PROCEDURE Variance* (data: ARRAY OF REAL; Count: INTEGER): REAL; +VAR + a: REAL; + +BEGIN + IF Count = 1 THEN + a := 0.0 + ELSE + a := TotalVariance(data, Count) / FLT(Count - 1) + END + + RETURN a +END Variance; + + +(* Стандартное среднеквадратичное отклонение *) +PROCEDURE StdDev* (data: ARRAY OF REAL; Count: INTEGER): REAL; + RETURN Math.sqrt(Variance(data, Count)) +END StdDev; + + +(* Среднее арифметическое всех значений массива, и среднее отклонение *) +PROCEDURE MeanAndStdDev* (data: ARRAY OF REAL; Count: INTEGER; + VAR mean: REAL; VAR stdDev: REAL); +VAR + totalVariance: REAL; + +BEGIN + MeanAndTotalVariance(data, Count, mean, totalVariance); + IF Count < 2 THEN + stdDev := 0.0 + ELSE + stdDev := Math.sqrt(totalVariance / FLT(Count - 1)) + END +END MeanAndStdDev; + + +(* Евклидова норма для всех значений массива *) +PROCEDURE Norm* (data: ARRAY OF REAL; Count: INTEGER): REAL; +VAR + a: REAL; + i: INTEGER; + +BEGIN + a := 0.0; + FOR i := 0 TO Count - 1 DO + a := a + Math.sqrr(data[i]) + END + + RETURN Math.sqrt(a) +END Norm; + + +END MathStat. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Math/Rand.ob07 b/programs/develop/oberon07/Lib/Math/Rand.ob07 new file mode 100644 index 000000000..c13deb6f3 --- /dev/null +++ b/programs/develop/oberon07/Lib/Math/Rand.ob07 @@ -0,0 +1,81 @@ +(* ************************************ + Генератор какбыслучайных чисел, + Линейный конгруэнтный метод, + алгоритм Лемера. + Вадим Исаев, 2020 + ------------------------------- + Generator pseudorandom numbers, + Linear congruential generator, + Algorithm by D. H. Lehmer. + Vadim Isaev, 2020 +*************************************** *) + +MODULE Rand; + +IMPORT HOST, Math; + + +CONST + + RAND_MAX = 2147483647; + + +VAR + seed: INTEGER; + + +PROCEDURE Randomize*; +BEGIN + seed := HOST.GetTickCount() +END Randomize; + + +(* Целые какбыслучайные числа до RAND_MAX *) +PROCEDURE RandomI* (): INTEGER; +CONST + a = 630360016; + +BEGIN + seed := (a * seed) MOD RAND_MAX + RETURN seed +END RandomI; + + +(* Какбыслучайные числа с плавающей запятой от 0 до 1 *) +PROCEDURE RandomR* (): REAL; + RETURN FLT(RandomI()) / FLT(RAND_MAX) +END RandomR; + + +(* Какбыслучайное число в диапазоне от 0 до l. + Return a random number in a range 0 ... l *) +PROCEDURE RandomITo* (aTo: INTEGER): INTEGER; + RETURN FLOOR(RandomR() * FLT(aTo)) +END RandomITo; + + +(* Какбыслучайное число в диапазоне. + Return a random number in a range *) +PROCEDURE RandomIRange* (aFrom, aTo: INTEGER): INTEGER; + RETURN FLOOR(RandomR() * FLT(aTo - aFrom)) + aFrom +END RandomIRange; + + +(* Какбыслучайное число. Распределение Гаусса *) +PROCEDURE RandG* (mean, stddev: REAL): REAL; +VAR + U, S: REAL; + +BEGIN + REPEAT + U := 2.0 * RandomR() - 1.0; + S := Math.sqrr(U) + Math.sqrr(2.0 * RandomR() - 1.0) + UNTIL (1.0E-20 < S) & (S <= 1.0) + + RETURN Math.sqrt(-2.0 * Math.ln(S) / S) * U * stddev + mean +END RandG; + + +BEGIN + seed := 654321 +END Rand. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Math/RandExt.ob07 b/programs/develop/oberon07/Lib/Math/RandExt.ob07 new file mode 100644 index 000000000..1d35795b2 --- /dev/null +++ b/programs/develop/oberon07/Lib/Math/RandExt.ob07 @@ -0,0 +1,298 @@ +(* ************************************************************ + Дополнительные алгоритмы генераторов какбыслучайных чисел. + Вадим Исаев, 2020 + + Additional generators of pseudorandom numbers. + Vadim Isaev, 2020 + ************************************************************ *) + +MODULE RandExt; + +IMPORT HOST, MathRound, MathBits; + +CONST + (* Для алгоритма Мерсена-Твистера *) + N = 624; + M = 397; + MATRIX_A = 9908B0DFH; (* constant vector a *) + UPPER_MASK = 80000000H; (* most significant w-r bits *) + LOWER_MASK = 7FFFFFFFH; (* least significant r bits *) + INT_MAX = 4294967295; + + +TYPE +(* структура служебных данных, для алгоритма mrg32k3a *) + random_t = RECORD + mrg32k3a_seed : REAL; + mrg32k3a_x : ARRAY 3 OF REAL; + mrg32k3a_y : ARRAY 3 OF REAL + END; + + (* Для алгоритма Мерсена-Твистера *) + MTKeyArray = ARRAY N OF INTEGER; + +VAR + (* Для алгоритма mrg32k3a *) + prndl: random_t; + (* Для алгоритма Мерсена-Твистера *) + mt : MTKeyArray; (* the array for the state vector *) + mti : INTEGER; (* mti == N+1 means mt[N] is not initialized *) + +(* --------------------------------------------------------------------------- + Генератор какбыслучайных чисел в диапазоне [a,b]. + Алгоритм 133б из книги "Агеев и др. - Бибилотека алгоритмов 101б-150б", + стр. 53. + Переделка из Algol на Oberon и доработка, Вадим Исаев, 2020 + + Generator pseudorandom numbers, algorithm 133b from + Comm ACM 5,10 (Oct 1962) 553. + Convert from Algol to Oberon Vadim Isaev, 2020. + + Входные параметры: + a - начальное вычисляемое значение, тип REAL; + b - конечное вычисляемое значение, тип REAL; + seed - начальное значение для генерации случайного числа. + Должно быть в диапазоне от 10 000 000 000 до 34 359 738 368 (2^35), + нечётное. + --------------------------------------------------------------------------- *) +PROCEDURE alg133b* (a, b: REAL; VAR seed: INTEGER): REAL; +CONST + m35 = 34359738368; + m36 = 68719476736; + m37 = 137438953472; + +VAR + x: INTEGER; +BEGIN + IF seed # 0 THEN + IF (seed MOD 2 = 0) THEN + seed := seed + 1 + END; + x:=seed; + seed:=0; + END; + + x:=5*x; + IF x>=m37 THEN + x:=x-m37 + END; + IF x>=m36 THEN + x:=x-m36 + END; + IF x>=m35 THEN + x:=x-m35 + END; + + RETURN FLT(x) / FLT(m35) * (b - a) + a +END alg133b; + +(* ---------------------------------------------------------- + Генератор почти равномерно распределённых + какбыслучайных чисел mrg32k3a + (Combined Multiple Recursive Generator) от 0 до 1. + Период повторения последовательности = 2^127 + + Generator pseudorandom numbers, + algorithm mrg32k3a. + + Переделка из FreePascal на Oberon, Вадим Исаев, 2020 + Convert from FreePascal to Oberon, Vadim Isaev, 2020 + ---------------------------------------------------------- *) +(* Инициализация генератора. + + Входные параметры: + seed - значение для инициализации. Любое. Если передать + ноль, то вместо ноля будет подставлено кол-во + процессорных тиков. *) +PROCEDURE mrg32k3a_init* (seed: REAL); +BEGIN + prndl.mrg32k3a_x[0] := 1.0; + prndl.mrg32k3a_x[1] := 1.0; + prndl.mrg32k3a_y[0] := 1.0; + prndl.mrg32k3a_y[1] := 1.0; + prndl.mrg32k3a_y[2] := 1.0; + + IF seed # 0.0 THEN + prndl.mrg32k3a_x[2] := seed; + ELSE + prndl.mrg32k3a_x[2] := FLT(HOST.GetTickCount()); + END; + +END mrg32k3a_init; + +(* Генератор какбыслучайных чисел от 0.0 до 1.0. *) +PROCEDURE mrg32k3a* (): REAL; + +CONST + (* random MRG32K3A algorithm constants *) + MRG32K3A_NORM = 2.328306549295728E-10; + MRG32K3A_M1 = 4294967087.0; + MRG32K3A_M2 = 4294944443.0; + MRG32K3A_A12 = 1403580.0; + MRG32K3A_A13 = 810728.0; + MRG32K3A_A21 = 527612.0; + MRG32K3A_A23 = 1370589.0; + RAND_BUFSIZE = 512; + +VAR + + xn, yn, result: REAL; + +BEGIN + (* Часть 1 *) + xn := MRG32K3A_A12 * prndl.mrg32k3a_x[1] - MRG32K3A_A13 * prndl.mrg32k3a_x[2]; + xn := xn - MathRound.trunc(xn / MRG32K3A_M1) * MRG32K3A_M1; + IF xn < 0.0 THEN + xn := xn + MRG32K3A_M1; + END; + + prndl.mrg32k3a_x[2] := prndl.mrg32k3a_x[1]; + prndl.mrg32k3a_x[1] := prndl.mrg32k3a_x[0]; + prndl.mrg32k3a_x[0] := xn; + + (* Часть 2 *) + yn := MRG32K3A_A21 * prndl.mrg32k3a_y[0] - MRG32K3A_A23 * prndl.mrg32k3a_y[2]; + yn := yn - MathRound.trunc(yn / MRG32K3A_M2) * MRG32K3A_M2; + IF yn < 0.0 THEN + yn := yn + MRG32K3A_M2; + END; + + prndl.mrg32k3a_y[2] := prndl.mrg32k3a_y[1]; + prndl.mrg32k3a_y[1] := prndl.mrg32k3a_y[0]; + prndl.mrg32k3a_y[0] := yn; + + (* Смешение частей *) + IF xn <= yn THEN + result := ((xn - yn + MRG32K3A_M1) * MRG32K3A_NORM) + ELSE + result := (xn - yn) * MRG32K3A_NORM; + END; + + RETURN result +END mrg32k3a; + + +(* ------------------------------------------------------------------- + Генератор какбыслучайных чисел, алгоритм Мерсена-Твистера (MT19937). + Переделка из Delphi в Oberon Вадим Исаев, 2020. + + Mersenne Twister Random Number Generator. + + A C-program for MT19937, with initialization improved 2002/1/26. + Coded by Takuji Nishimura and Makoto Matsumoto. + + Adapted for DMath by Jean Debord - Feb. 2007 + Adapted for Oberon-07 by Vadim Isaev - May 2020 + ------------------------------------------------------------ *) +(* Initializes MT generator with a seed *) +PROCEDURE InitMT(Seed : INTEGER); +VAR + i : INTEGER; +BEGIN + mt[0] := MathBits.iand(Seed, INT_MAX); + FOR i := 1 TO N-1 DO + mt[i] := (1812433253 * MathBits.ixor(mt[i-1], LSR(mt[i-1], 30)) + i); + (* See Knuth TAOCP Vol2. 3rd Ed. P.106 For multiplier. + In the previous versions, MSBs of the seed affect + only MSBs of the array mt[]. + 2002/01/09 modified by Makoto Matsumoto *) + mt[i] := MathBits.iand(mt[i], INT_MAX); + (* For >32 Bit machines *) + END; + mti := N; +END InitMT; + +(* Initialize MT generator with an array InitKey[0..(KeyLength - 1)] *) +PROCEDURE InitMTbyArray(InitKey : MTKeyArray; KeyLength : INTEGER); +VAR + i, j, k, k1 : INTEGER; +BEGIN + InitMT(19650218); + + i := 1; + j := 0; + + IF N > KeyLength THEN + k1 := N + ELSE + k1 := KeyLength; + END; + + FOR k := k1 TO 1 BY -1 DO + (* non linear *) + mt[i] := MathBits.ixor(mt[i], (MathBits.ixor(mt[i-1], LSR(mt[i-1], 30)) * 1664525)) + InitKey[j] + j; + mt[i] := MathBits.iand(mt[i], INT_MAX); (* for WORDSIZE > 32 machines *) + INC(i); + INC(j); + IF i >= N THEN + mt[0] := mt[N-1]; + i := 1; + END; + IF j >= KeyLength THEN + j := 0; + END; + END; + + FOR k := N-1 TO 1 BY -1 DO + (* non linear *) + mt[i] := MathBits.ixor(mt[i], (MathBits.ixor(mt[i-1], LSR(mt[i-1], 30)) * 1566083941)) - i; + mt[i] := MathBits.iand(mt[i], INT_MAX); (* for WORDSIZE > 32 machines *) + INC(i); + IF i >= N THEN + mt[0] := mt[N-1]; + i := 1; + END; + END; + + mt[0] := UPPER_MASK; (* MSB is 1; assuring non-zero initial array *) + +END InitMTbyArray; + +(* Generates a integer Random number on [-2^31 .. 2^31 - 1] interval *) +PROCEDURE IRanMT(): INTEGER; +VAR + mag01 : ARRAY 2 OF INTEGER; + y,k : INTEGER; +BEGIN + IF mti >= N THEN (* generate N words at one Time *) + (* If IRanMT() has not been called, a default initial seed is used *) + IF mti = N + 1 THEN + InitMT(5489); + END; + + FOR k := 0 TO (N-M)-1 DO + y := MathBits.ior(MathBits.iand(mt[k], UPPER_MASK), MathBits.iand(mt[k+1], LOWER_MASK)); + mt[k] := MathBits.ixor(MathBits.ixor(mt[k+M], LSR(y, 1)), mag01[MathBits.iand(y, 1H)]); + END; + + FOR k := (N-M) TO (N-2) DO + y := MathBits.ior(MathBits.iand(mt[k], UPPER_MASK), MathBits.iand(mt[k+1], LOWER_MASK)); + mt[k] := MathBits.ixor(mt[k - (N - M)], MathBits.ixor(LSR(y, 1), mag01[MathBits.iand(y, 1H)])); + END; + + y := MathBits.ior(MathBits.iand(mt[N-1], UPPER_MASK), MathBits.iand(mt[0], LOWER_MASK)); + mt[N-1] := MathBits.ixor(mt[M-1], MathBits.ixor(LSR(y, 1), mag01[MathBits.iand(y, 1H)])); + + mti := 0; + END; + + y := mt[mti]; + INC(mti); + + (* Tempering *) + y := MathBits.ixor(y, LSR(y, 11)); + y := MathBits.ixor(y, MathBits.iand(LSL(y, 7), 9D2C5680H)); + y := MathBits.ixor(y, MathBits.iand(LSL(y, 15), 4022730752)); + y := MathBits.ixor(y, LSR(y, 18)); + + RETURN y +END IRanMT; + +(* Generates a real Random number on [0..1] interval *) +PROCEDURE RRanMT(): REAL; +BEGIN + RETURN FLT(IRanMT())/FLT(INT_MAX) +END RRanMT; + + +END RandExt. diff --git a/programs/develop/oberon07/Lib/RVM32I/FPU.ob07 b/programs/develop/oberon07/Lib/RVM32I/FPU.ob07 new file mode 100644 index 000000000..da30e4ea7 --- /dev/null +++ b/programs/develop/oberon07/Lib/RVM32I/FPU.ob07 @@ -0,0 +1,465 @@ +(* + BSD 2-Clause License + + Copyright (c) 2020, Anton Krotov + All rights reserved. +*) + +MODULE FPU; + + +CONST + + INF = 07F800000H; + NINF = 0FF800000H; + NAN = 07FC00000H; + + +PROCEDURE div2 (b, a: INTEGER): INTEGER; +VAR + n, e, r, s: INTEGER; + +BEGIN + s := ORD(BITS(a) / BITS(b) - {0..30}); + e := (a DIV 800000H) MOD 256 - (b DIV 800000H) MOD 256 + 127; + + a := a MOD 800000H + 800000H; + b := b MOD 800000H + 800000H; + + n := 800000H; + r := 0; + + IF a < b THEN + a := a * 2; + DEC(e) + END; + + WHILE (a > 0) & (n > 0) DO + IF a >= b THEN + INC(r, n); + DEC(a, b) + END; + a := a * 2; + n := n DIV 2 + END; + + IF e <= 0 THEN + e := 0; + r := 800000H; + s := 0 + ELSIF e >= 255 THEN + e := 255; + r := 800000H + END + + RETURN (r - 800000H) + e * 800000H + s +END div2; + + +PROCEDURE mul2 (b, a: INTEGER): INTEGER; +VAR + e, r, s: INTEGER; + +BEGIN + s := ORD(BITS(a) / BITS(b) - {0..30}); + e := (a DIV 800000H) MOD 256 + (b DIV 800000H) MOD 256 - 127; + + a := a MOD 800000H + 800000H; + b := b MOD 800000H + 800000H; + + r := a * (b MOD 256); + b := b DIV 256; + r := LSR(r, 8); + + INC(r, a * (b MOD 256)); + b := b DIV 256; + r := LSR(r, 8); + + INC(r, a * (b MOD 256)); + r := LSR(r, 7); + + IF r >= 1000000H THEN + r := r DIV 2; + INC(e) + END; + + IF e <= 0 THEN + e := 0; + r := 800000H; + s := 0 + ELSIF e >= 255 THEN + e := 255; + r := 800000H + END + + RETURN (r - 800000H) + e * 800000H + s +END mul2; + + +PROCEDURE add2 (b, a: INTEGER): INTEGER; +VAR + ea, eb, e, d, r: INTEGER; + +BEGIN + ea := (a DIV 800000H) MOD 256; + eb := (b DIV 800000H) MOD 256; + d := ea - eb; + + a := a MOD 800000H + 800000H; + b := b MOD 800000H + 800000H; + + IF d > 0 THEN + IF d < 24 THEN + b := LSR(b, d) + ELSE + b := 0 + END; + e := ea + ELSIF d < 0 THEN + IF d > -24 THEN + a := LSR(a, -d) + ELSE + a := 0 + END; + e := eb + ELSE + e := ea + END; + + r := a + b; + + IF r >= 1000000H THEN + r := r DIV 2; + INC(e) + END; + + IF e >= 255 THEN + e := 255; + r := 800000H + END + + RETURN (r - 800000H) + e * 800000H +END add2; + + +PROCEDURE sub2 (b, a: INTEGER): INTEGER; +VAR + ea, eb, e, d, r, s: INTEGER; + +BEGIN + ea := (a DIV 800000H) MOD 256; + eb := (b DIV 800000H) MOD 256; + + a := a MOD 800000H + 800000H; + b := b MOD 800000H + 800000H; + + d := ea - eb; + + IF (d > 0) OR (d = 0) & (a >= b) THEN + s := 0 + ELSE + ea := eb; + d := -d; + r := a; + a := b; + b := r; + s := 80000000H + END; + + e := ea; + + IF d > 0 THEN + IF d < 24 THEN + b := LSR(b, d) + ELSE + b := 0 + END + END; + + r := a - b; + + IF r = 0 THEN + e := 0; + r := 800000H; + s := 0 + ELSE + WHILE r < 800000H DO + r := r * 2; + DEC(e) + END + END; + + IF e <= 0 THEN + e := 0; + r := 800000H; + s := 0 + END + + RETURN (r - 800000H) + e * 800000H + s +END sub2; + + +PROCEDURE zero (VAR x: INTEGER); +BEGIN + IF BITS(x) * {23..30} = {} THEN + x := 0 + END +END zero; + + +PROCEDURE isNaN (a: INTEGER): BOOLEAN; + RETURN (a > INF) OR (a < 0) & (a > NINF) +END isNaN; + + +PROCEDURE isInf (a: INTEGER): BOOLEAN; + RETURN (a = INF) OR (a = NINF) +END isInf; + + +PROCEDURE isNormal (a: INTEGER): BOOLEAN; + RETURN (BITS(a) * {23..30} # {23..30}) & (BITS(a) * {23..30} # {}) +END isNormal; + + +PROCEDURE add* (b, a: INTEGER): INTEGER; +VAR + r: INTEGER; + +BEGIN + zero(a); zero(b); + + IF isNormal(a) & isNormal(b) THEN + + IF (a > 0) & (b > 0) THEN + r := add2(b, a) + ELSIF (a < 0) & (b < 0) THEN + r := add2(b, a) + 80000000H + ELSIF (a > 0) & (b < 0) THEN + r := sub2(b, a) + ELSIF (a < 0) & (b > 0) THEN + r := sub2(a, b) + END + + ELSIF isNaN(a) OR isNaN(b) THEN + r := NAN + ELSIF isInf(a) & isInf(b) THEN + IF a = b THEN + r := a + ELSE + r := NAN + END + ELSIF isInf(a) THEN + r := a + ELSIF isInf(b) THEN + r := b + ELSIF a = 0 THEN + r := b + ELSIF b = 0 THEN + r := a + END + + RETURN r +END add; + + +PROCEDURE sub* (b, a: INTEGER): INTEGER; +VAR + r: INTEGER; + +BEGIN + zero(a); zero(b); + + IF isNormal(a) & isNormal(b) THEN + + IF (a > 0) & (b > 0) THEN + r := sub2(b, a) + ELSIF (a < 0) & (b < 0) THEN + r := sub2(a, b) + ELSIF (a > 0) & (b < 0) THEN + r := add2(b, a) + ELSIF (a < 0) & (b > 0) THEN + r := add2(b, a) + 80000000H + END + + ELSIF isNaN(a) OR isNaN(b) THEN + r := NAN + ELSIF isInf(a) & isInf(b) THEN + IF a # b THEN + r := a + ELSE + r := NAN + END + ELSIF isInf(a) THEN + r := a + ELSIF isInf(b) THEN + r := INF + ORD(BITS(b) / {31} - {0..30}) + ELSIF (a = 0) & (b = 0) THEN + r := 0 + ELSIF a = 0 THEN + r := ORD(BITS(b) / {31}) + ELSIF b = 0 THEN + r := a + END + + RETURN r +END sub; + + +PROCEDURE mul* (b, a: INTEGER): INTEGER; +VAR + r: INTEGER; + +BEGIN + zero(a); zero(b); + + IF isNormal(a) & isNormal(b) THEN + r := mul2(b, a) + ELSIF isNaN(a) OR isNaN(b) THEN + r := NAN + ELSIF (isInf(a) & (b = 0)) OR (isInf(b) & (a = 0)) THEN + r := NAN + ELSIF isInf(a) OR isInf(b) THEN + r := INF + ORD(BITS(a) / BITS(b) - {0..30}) + ELSIF (a = 0) OR (b = 0) THEN + r := 0 + END + + RETURN r +END mul; + + +PROCEDURE _div* (b, a: INTEGER): INTEGER; +VAR + r: INTEGER; + +BEGIN + zero(a); zero(b); + + IF isNormal(a) & isNormal(b) THEN + r := div2(b, a) + ELSIF isNaN(a) OR isNaN(b) THEN + r := NAN + ELSIF isInf(a) & isInf(b) THEN + r := NAN + ELSIF isInf(a) THEN + r := INF + ORD(BITS(a) / BITS(b) - {0..30}) + ELSIF isInf(b) THEN + r := 0 + ELSIF a = 0 THEN + IF b = 0 THEN + r := NAN + ELSE + r := 0 + END + ELSIF b = 0 THEN + IF a > 0 THEN + r := INF + ELSE + r := NINF + END + END + + RETURN r +END _div; + + +PROCEDURE cmp* (op, b, a: INTEGER): BOOLEAN; +VAR + res: BOOLEAN; + +BEGIN + zero(a); zero(b); + + IF isNaN(a) OR isNaN(b) THEN + res := op = 1 + ELSIF (a < 0) & (b < 0) THEN + CASE op OF + |0: res := a = b + |1: res := a # b + |2: res := a > b + |3: res := a >= b + |4: res := a < b + |5: res := a <= b + END + ELSE + CASE op OF + |0: res := a = b + |1: res := a # b + |2: res := a < b + |3: res := a <= b + |4: res := a > b + |5: res := a >= b + END + END + + RETURN res +END cmp; + + +PROCEDURE flt* (x: INTEGER): INTEGER; +VAR + n, y, r, s: INTEGER; + +BEGIN + IF x = 0 THEN + s := 0; + r := 800000H; + n := -126 + ELSIF x = 80000000H THEN + s := 80000000H; + r := 800000H; + n := 32 + ELSE + IF x < 0 THEN + s := 80000000H + ELSE + s := 0 + END; + n := 0; + y := ABS(x); + r := y; + WHILE y > 0 DO + y := y DIV 2; + INC(n) + END; + IF n > 24 THEN + r := LSR(r, n - 24) + ELSE + r := LSL(r, 24 - n) + END + END + + RETURN (r - 800000H) + (n + 126) * 800000H + s +END flt; + + +PROCEDURE floor* (x: INTEGER): INTEGER; +VAR + r, e: INTEGER; + +BEGIN + zero(x); + + e := (x DIV 800000H) MOD 256 - 127; + r := x MOD 800000H + 800000H; + + IF (0 <= e) & (e <= 22) THEN + r := LSR(r, 23 - e) + ORD((x < 0) & (LSL(r, e + 9) # 0)) + ELSIF (23 <= e) & (e <= 54) THEN + r := LSL(r, e - 23) + ELSIF (e < 0) & (x < 0) THEN + r := 1 + ELSE + r := 0 + END; + + IF x < 0 THEN + r := -r + END + + RETURN r +END floor; + + +END FPU. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/RVM32I/HOST.ob07 b/programs/develop/oberon07/Lib/RVM32I/HOST.ob07 new file mode 100644 index 000000000..380b75c35 --- /dev/null +++ b/programs/develop/oberon07/Lib/RVM32I/HOST.ob07 @@ -0,0 +1,176 @@ +(* + BSD 2-Clause License + + Copyright (c) 2020, Anton Krotov + All rights reserved. +*) + +MODULE HOST; + +IMPORT SYSTEM, Trap; + + +CONST + + slash* = "\"; + eol* = 0DX + 0AX; + + bit_depth* = 32; + maxint* = 7FFFFFFFH; + minint* = 80000000H; + + +VAR + + maxreal*: REAL; + + +PROCEDURE syscall0 (fn: INTEGER): INTEGER; +BEGIN + Trap.syscall(SYSTEM.ADR(fn)) + RETURN fn +END syscall0; + + +PROCEDURE syscall1 (fn, p1: INTEGER): INTEGER; +BEGIN + Trap.syscall(SYSTEM.ADR(fn)) + RETURN fn +END syscall1; + + +PROCEDURE syscall2 (fn, p1, p2: INTEGER): INTEGER; +BEGIN + Trap.syscall(SYSTEM.ADR(fn)) + RETURN fn +END syscall2; + + +PROCEDURE syscall3 (fn, p1, p2, p3: INTEGER): INTEGER; +BEGIN + Trap.syscall(SYSTEM.ADR(fn)) + RETURN fn +END syscall3; + + +PROCEDURE syscall4 (fn, p1, p2, p3, p4: INTEGER): INTEGER; +BEGIN + Trap.syscall(SYSTEM.ADR(fn)) + RETURN fn +END syscall4; + + +PROCEDURE ExitProcess* (code: INTEGER); +BEGIN + code := syscall1(0, code) +END ExitProcess; + + +PROCEDURE GetCurrentDirectory* (VAR path: ARRAY OF CHAR); +VAR + a: INTEGER; +BEGIN + a := syscall2(1, LEN(path), SYSTEM.ADR(path[0])) +END GetCurrentDirectory; + + +PROCEDURE GetArg* (n: INTEGER; VAR s: ARRAY OF CHAR); +BEGIN + n := syscall3(2, n, LEN(s), SYSTEM.ADR(s[0])) +END GetArg; + + +PROCEDURE FileRead* (F: INTEGER; VAR Buffer: ARRAY OF CHAR; bytes: INTEGER): INTEGER; + RETURN syscall4(3, F, LEN(Buffer), SYSTEM.ADR(Buffer[0]), bytes) +END FileRead; + + +PROCEDURE FileWrite* (F: INTEGER; Buffer: ARRAY OF BYTE; bytes: INTEGER): INTEGER; + RETURN syscall4(4, F, LEN(Buffer), SYSTEM.ADR(Buffer[0]), bytes) +END FileWrite; + + +PROCEDURE FileCreate* (FName: ARRAY OF CHAR): INTEGER; + RETURN syscall2(5, LEN(FName), SYSTEM.ADR(FName[0])) +END FileCreate; + + +PROCEDURE FileClose* (F: INTEGER); +BEGIN + F := syscall1(6, F) +END FileClose; + + +PROCEDURE FileOpen* (FName: ARRAY OF CHAR): INTEGER; + RETURN syscall2(7, LEN(FName), SYSTEM.ADR(FName[0])) +END FileOpen; + + +PROCEDURE chmod* (FName: ARRAY OF CHAR); +VAR + a: INTEGER; +BEGIN + a := syscall2(12, LEN(FName), SYSTEM.ADR(FName[0])) +END chmod; + + +PROCEDURE OutChar* (c: CHAR); +VAR + a: INTEGER; +BEGIN + a := syscall1(8, ORD(c)) +END OutChar; + + +PROCEDURE GetTickCount* (): INTEGER; + RETURN syscall0(9) +END GetTickCount; + + +PROCEDURE isRelative* (path: ARRAY OF CHAR): BOOLEAN; + RETURN syscall2(11, LEN(path), SYSTEM.ADR(path[0])) # 0 +END isRelative; + + +PROCEDURE UnixTime* (): INTEGER; + RETURN syscall0(10) +END UnixTime; + + +PROCEDURE s2d (x: INTEGER; VAR h, l: INTEGER); +VAR + s, e, f: INTEGER; +BEGIN + s := ASR(x, 31) MOD 2; + f := x MOD 800000H; + e := (x DIV 800000H) MOD 256; + IF e = 255 THEN + e := 2047 + ELSE + INC(e, 896) + END; + h := LSL(s, 31) + LSL(e, 20) + (f DIV 8); + l := (f MOD 8) * 20000000H +END s2d; + + +PROCEDURE d2s* (x: REAL): INTEGER; +VAR + i: INTEGER; +BEGIN + SYSTEM.GET(SYSTEM.ADR(x), i) + RETURN i +END d2s; + + +PROCEDURE splitf* (x: REAL; VAR a, b: INTEGER): INTEGER; +BEGIN + s2d(d2s(x), b, a) + RETURN a +END splitf; + + +BEGIN + maxreal := 1.9; + PACK(maxreal, 127) +END HOST. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/RVM32I/Out.ob07 b/programs/develop/oberon07/Lib/RVM32I/Out.ob07 new file mode 100644 index 000000000..aad7567e7 --- /dev/null +++ b/programs/develop/oberon07/Lib/RVM32I/Out.ob07 @@ -0,0 +1,273 @@ +(* + BSD 2-Clause License + + Copyright (c) 2016, 2018, 2020, Anton Krotov + All rights reserved. +*) + +MODULE Out; + +IMPORT HOST, SYSTEM; + + +PROCEDURE Char* (c: CHAR); +BEGIN + HOST.OutChar(c) +END Char; + + +PROCEDURE String* (s: ARRAY OF CHAR); +VAR + i, n: INTEGER; + +BEGIN + n := LENGTH(s) - 1; + FOR i := 0 TO n DO + Char(s[i]) + END +END String; + + +PROCEDURE Int* (x, width: INTEGER); +VAR + i, a: INTEGER; + str: ARRAY 12 OF CHAR; + +BEGIN + IF x = 80000000H THEN + COPY("-2147483648", str); + DEC(width, 11) + ELSE + i := 0; + IF x < 0 THEN + x := -x; + i := 1; + str[0] := "-" + END; + + a := x; + REPEAT + INC(i); + a := a DIV 10 + UNTIL a = 0; + + str[i] := 0X; + DEC(width, i); + + REPEAT + DEC(i); + str[i] := CHR(x MOD 10 + ORD("0")); + x := x DIV 10 + UNTIL x = 0 + END; + + WHILE width > 0 DO + Char(20X); + DEC(width) + END; + + String(str) +END Int; + + +PROCEDURE Inf (x: REAL; width: INTEGER); +VAR + s: ARRAY 5 OF CHAR; + +BEGIN + DEC(width, 4); + IF x # x THEN + s := " Nan" + ELSIF x = SYSTEM.INF() THEN + s := "+Inf" + ELSIF x = -SYSTEM.INF() THEN + s := "-Inf" + END; + + WHILE width > 0 DO + Char(20X); + DEC(width) + END; + + String(s) +END Inf; + + +PROCEDURE Ln*; +BEGIN + Char(0DX); + Char(0AX) +END Ln; + + +PROCEDURE unpk10 (VAR x: REAL; VAR n: INTEGER); +VAR + a, b: REAL; + +BEGIN + ASSERT(x > 0.0); + n := 0; + WHILE x < 1.0 DO + x := x * 10.0; + DEC(n) + END; + + a := 10.0; + b := 1.0; + + WHILE a <= x DO + b := a; + a := a * 10.0; + INC(n) + END; + x := x / b +END unpk10; + + +PROCEDURE _Real (x: REAL; width: INTEGER); +VAR + n, k, p: INTEGER; + +BEGIN + p := MIN(MAX(width - 7, 1), 10); + + width := width - p - 7; + WHILE width > 0 DO + Char(20X); + DEC(width) + END; + + IF x < 0.0 THEN + Char("-"); + x := -x + ELSE + Char(20X) + END; + + unpk10(x, n); + + k := FLOOR(x); + Char(CHR(k + 30H)); + Char("."); + + WHILE p > 0 DO + x := (x - FLT(k)) * 10.0; + k := FLOOR(x); + Char(CHR(k + 30H)); + DEC(p) + END; + + Char("E"); + IF n >= 0 THEN + Char("+") + ELSE + Char("-") + END; + n := ABS(n); + Char(CHR(n DIV 10 + 30H)); + Char(CHR(n MOD 10 + 30H)) +END _Real; + + +PROCEDURE Real* (x: REAL; width: INTEGER); +BEGIN + IF (x # x) OR (ABS(x) = SYSTEM.INF()) THEN + Inf(x, width) + ELSIF x = 0.0 THEN + WHILE width > 17 DO + Char(20X); + DEC(width) + END; + DEC(width, 8); + String(" 0.0"); + WHILE width > 0 DO + Char("0"); + DEC(width) + END; + String("E+00") + ELSE + _Real(x, width) + END +END Real; + + +PROCEDURE _FixReal (x: REAL; width, p: INTEGER); +VAR + n, k: INTEGER; + minus: BOOLEAN; + +BEGIN + minus := x < 0.0; + IF minus THEN + x := -x + END; + + unpk10(x, n); + + DEC(width, 3 + MAX(p, 0) + MAX(n, 0)); + WHILE width > 0 DO + Char(20X); + DEC(width) + END; + + IF minus THEN + Char("-") + ELSE + Char(20X) + END; + + IF n < 0 THEN + INC(n); + Char("0"); + Char("."); + WHILE (n < 0) & (p > 0) DO + Char("0"); + INC(n); + DEC(p) + END + ELSE + WHILE n >= 0 DO + k := FLOOR(x); + Char(CHR(k + 30H)); + x := (x - FLT(k)) * 10.0; + DEC(n) + END; + Char(".") + END; + + WHILE p > 0 DO + k := FLOOR(x); + Char(CHR(k + 30H)); + x := (x - FLT(k)) * 10.0; + DEC(p) + END + +END _FixReal; + + +PROCEDURE FixReal* (x: REAL; width, p: INTEGER); +BEGIN + IF (x # x) OR (ABS(x) = SYSTEM.INF()) THEN + Inf(x, width) + ELSIF x = 0.0 THEN + DEC(width, 3 + MAX(p, 0)); + WHILE width > 0 DO + Char(20X); + DEC(width) + END; + String(" 0."); + WHILE p > 0 DO + Char("0"); + DEC(p) + END + ELSE + _FixReal(x, width, p) + END +END FixReal; + + +PROCEDURE Open*; +END Open; + + +END Out. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/RVM32I/RTL.ob07 b/programs/develop/oberon07/Lib/RVM32I/RTL.ob07 new file mode 100644 index 000000000..8e12fed58 --- /dev/null +++ b/programs/develop/oberon07/Lib/RVM32I/RTL.ob07 @@ -0,0 +1,390 @@ +(* + BSD 2-Clause License + + Copyright (c) 2019-2020, Anton Krotov + All rights reserved. +*) + +MODULE RTL; + +IMPORT SYSTEM, F := FPU, Trap; + + +CONST + + bit_depth = 32; + maxint = 7FFFFFFFH; + minint = 80000000H; + + WORD = bit_depth DIV 8; + MAX_SET = bit_depth - 1; + + +VAR + + Heap, Types, TypesCount: INTEGER; + + +PROCEDURE _error* (modnum, _module, err, line: INTEGER); +BEGIN + Trap.trap(modnum, _module, err, line) +END _error; + + +PROCEDURE _fmul* (b, a: INTEGER): INTEGER; + RETURN F.mul(b, a) +END _fmul; + + +PROCEDURE _fdiv* (b, a: INTEGER): INTEGER; + RETURN F._div(b, a) +END _fdiv; + + +PROCEDURE _fdivi* (b, a: INTEGER): INTEGER; + RETURN F._div(a, b) +END _fdivi; + + +PROCEDURE _fadd* (b, a: INTEGER): INTEGER; + RETURN F.add(b, a) +END _fadd; + + +PROCEDURE _fsub* (b, a: INTEGER): INTEGER; + RETURN F.sub(b, a) +END _fsub; + + +PROCEDURE _fsubi* (b, a: INTEGER): INTEGER; + RETURN F.sub(a, b) +END _fsubi; + + +PROCEDURE _fcmp* (op, b, a: INTEGER): BOOLEAN; + RETURN F.cmp(op, b, a) +END _fcmp; + + +PROCEDURE _floor* (x: INTEGER): INTEGER; + RETURN F.floor(x) +END _floor; + + +PROCEDURE _flt* (x: INTEGER): INTEGER; + RETURN F.flt(x) +END _flt; + + +PROCEDURE _pack* (n: INTEGER; VAR x: SET); +BEGIN + n := LSL((LSR(ORD(x), 23) MOD 256 + n) MOD 256, 23); + x := x - {23..30} + BITS(n) +END _pack; + + +PROCEDURE _unpk* (VAR n: INTEGER; VAR x: SET); +BEGIN + n := LSR(ORD(x), 23) MOD 256 - 127; + x := x - {30} + {23..29} +END _unpk; + + +PROCEDURE _rot* (VAR A: ARRAY OF INTEGER); +VAR + i, n, k: INTEGER; + +BEGIN + k := LEN(A) - 1; + n := A[0]; + i := 0; + WHILE i < k DO + A[i] := A[i + 1]; + INC(i) + END; + A[k] := n +END _rot; + + +PROCEDURE _set* (b, a: INTEGER): INTEGER; +BEGIN + IF (a <= b) & (a <= MAX_SET) & (b >= 0) THEN + IF b > MAX_SET THEN + b := MAX_SET + END; + IF a < 0 THEN + a := 0 + END; + a := LSR(ASR(minint, b - a), MAX_SET - b) + ELSE + a := 0 + END + + RETURN a +END _set; + + +PROCEDURE _set1* (a: INTEGER): INTEGER; +BEGIN + IF ASR(a, 5) = 0 THEN + a := LSL(1, a) + ELSE + a := 0 + END + RETURN a +END _set1; + + +PROCEDURE _length* (len, str: INTEGER): INTEGER; +VAR + c: CHAR; + res: INTEGER; + +BEGIN + res := 0; + REPEAT + SYSTEM.GET(str, c); + INC(str); + DEC(len); + INC(res) + UNTIL (len = 0) OR (c = 0X); + + RETURN res - ORD(c = 0X) +END _length; + + +PROCEDURE _move* (bytes, dest, source: INTEGER); +VAR + b: BYTE; + i: INTEGER; + +BEGIN + WHILE ((source MOD WORD # 0) OR (dest MOD WORD # 0)) & (bytes > 0) DO + SYSTEM.GET(source, b); + SYSTEM.PUT8(dest, b); + INC(source); + INC(dest); + DEC(bytes) + END; + + WHILE bytes >= WORD DO + SYSTEM.GET(source, i); + SYSTEM.PUT(dest, i); + INC(source, WORD); + INC(dest, WORD); + DEC(bytes, WORD) + END; + + WHILE bytes > 0 DO + SYSTEM.GET(source, b); + SYSTEM.PUT8(dest, b); + INC(source); + INC(dest); + DEC(bytes) + END +END _move; + + +PROCEDURE _lengthw* (len, str: INTEGER): INTEGER; +VAR + c: WCHAR; + res: INTEGER; + +BEGIN + res := 0; + REPEAT + SYSTEM.GET(str, c); + INC(str, 2); + DEC(len); + INC(res) + UNTIL (len = 0) OR (c = 0X); + + RETURN res - ORD(c = 0X) +END _lengthw; + + +PROCEDURE strncmp (a, b, n: INTEGER): INTEGER; +VAR + A, B: CHAR; + res: INTEGER; + +BEGIN + res := 0; + WHILE n > 0 DO + SYSTEM.GET(a, A); INC(a); + SYSTEM.GET(b, B); INC(b); + DEC(n); + IF A # B THEN + res := ORD(A) - ORD(B); + n := 0 + ELSIF A = 0X THEN + n := 0 + END + END + RETURN res +END strncmp; + + +PROCEDURE _strcmp* (op, len2, str2, len1, str1: INTEGER): BOOLEAN; +VAR + res: INTEGER; + bRes: BOOLEAN; + +BEGIN + res := strncmp(str1, str2, MIN(len1, len2)); + IF res = 0 THEN + res := _length(len1, str1) - _length(len2, str2) + END; + + CASE op OF + |0: bRes := res = 0 + |1: bRes := res # 0 + |2: bRes := res < 0 + |3: bRes := res <= 0 + |4: bRes := res > 0 + |5: bRes := res >= 0 + END + + RETURN bRes +END _strcmp; + + +PROCEDURE strncmpw (a, b, n: INTEGER): INTEGER; +VAR + A, B: WCHAR; + res: INTEGER; + +BEGIN + res := 0; + WHILE n > 0 DO + SYSTEM.GET(a, A); INC(a, 2); + SYSTEM.GET(b, B); INC(b, 2); + DEC(n); + IF A # B THEN + res := ORD(A) - ORD(B); + n := 0 + ELSIF A = WCHR(0) THEN + n := 0 + END + END + RETURN res +END strncmpw; + + +PROCEDURE _strcmpw* (op, len2, str2, len1, str1: INTEGER): BOOLEAN; +VAR + res: INTEGER; + bRes: BOOLEAN; + +BEGIN + res := strncmpw(str1, str2, MIN(len1, len2)); + IF res = 0 THEN + res := _lengthw(len1, str1) - _lengthw(len2, str2) + END; + + CASE op OF + |0: bRes := res = 0 + |1: bRes := res # 0 + |2: bRes := res < 0 + |3: bRes := res <= 0 + |4: bRes := res > 0 + |5: bRes := res >= 0 + END + + RETURN bRes +END _strcmpw; + + +PROCEDURE _arrcpy* (base_size, len_dst, dst, len_src, src: INTEGER): BOOLEAN; +VAR + res: BOOLEAN; + +BEGIN + IF len_src > len_dst THEN + res := FALSE + ELSE + _move(len_src * base_size, dst, src); + res := TRUE + END + + RETURN res +END _arrcpy; + + +PROCEDURE _strcpy* (chr_size, len_src, src, len_dst, dst: INTEGER); +BEGIN + _move(MIN(len_dst, len_src) * chr_size, dst, src) +END _strcpy; + + +PROCEDURE _new* (t, size: INTEGER; VAR p: INTEGER); +BEGIN + IF Heap + size < Trap.sp() - 64 THEN + p := Heap + WORD; + REPEAT + SYSTEM.PUT(Heap, t); + INC(Heap, WORD); + DEC(size, WORD); + t := 0 + UNTIL size = 0 + ELSE + p := 0 + END +END _new; + + +PROCEDURE _guard* (t, p: INTEGER): BOOLEAN; +VAR + _type: INTEGER; + +BEGIN + SYSTEM.GET(p, p); + IF p # 0 THEN + SYSTEM.GET(p - WORD, _type); + WHILE (_type # t) & (_type # 0) DO + SYSTEM.GET(Types + _type * WORD, _type) + END + ELSE + _type := t + END + + RETURN _type = t +END _guard; + + +PROCEDURE _is* (t, p: INTEGER): BOOLEAN; +VAR + _type: INTEGER; + +BEGIN + _type := 0; + IF p # 0 THEN + SYSTEM.GET(p - WORD, _type); + WHILE (_type # t) & (_type # 0) DO + SYSTEM.GET(Types + _type * WORD, _type) + END + END + + RETURN _type = t +END _is; + + +PROCEDURE _guardrec* (t0, t1: INTEGER): BOOLEAN; +BEGIN + WHILE (t1 # t0) & (t1 # 0) DO + SYSTEM.GET(Types + t1 * WORD, t1) + END + + RETURN t1 = t0 +END _guardrec; + + +PROCEDURE _init* (tcount, heap, types: INTEGER); +BEGIN + Heap := heap; + TypesCount := tcount; + Types := types +END _init; + + +END RTL. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/RVM32I/Trap.ob07 b/programs/develop/oberon07/Lib/RVM32I/Trap.ob07 new file mode 100644 index 000000000..55bff41f7 --- /dev/null +++ b/programs/develop/oberon07/Lib/RVM32I/Trap.ob07 @@ -0,0 +1,128 @@ +(* + BSD 2-Clause License + + Copyright (c) 2020, Anton Krotov + All rights reserved. +*) + +MODULE Trap; + +IMPORT SYSTEM; + + +PROCEDURE [code] sp* (): INTEGER + 22, 0, 4; (* MOV R0, SP *) + + +PROCEDURE [code] syscall* (ptr: INTEGER) + 22, 0, 4, (* MOV R0, SP *) + 27, 0, 4, (* ADD R0, 4 *) + 9, 0, 0, (* LDR32 R0, R0 *) + 80, 0, 0; (* SYSCALL R0 *) + + +PROCEDURE Char (c: CHAR); +VAR + a: ARRAY 2 OF INTEGER; + +BEGIN + a[0] := 8; + a[1] := ORD(c); + syscall(SYSTEM.ADR(a[0])) +END Char; + + +PROCEDURE String (s: ARRAY OF CHAR); +VAR + i: INTEGER; + +BEGIN + i := 0; + WHILE s[i] # 0X DO + Char(s[i]); + INC(i) + END +END String; + + +PROCEDURE PString (ptr: INTEGER); +VAR + c: CHAR; + +BEGIN + SYSTEM.GET(ptr, c); + WHILE c # 0X DO + Char(c); + INC(ptr); + SYSTEM.GET(ptr, c) + END +END PString; + + +PROCEDURE Ln; +BEGIN + String(0DX + 0AX) +END Ln; + + +PROCEDURE IntToStr (x: INTEGER; VAR str: ARRAY OF CHAR); +VAR + i, a: INTEGER; + +BEGIN + i := 0; + a := x; + REPEAT + INC(i); + a := a DIV 10 + UNTIL a = 0; + + str[i] := 0X; + + REPEAT + DEC(i); + str[i] := CHR(x MOD 10 + ORD("0")); + x := x DIV 10 + UNTIL x = 0 +END IntToStr; + + +PROCEDURE Int (x: INTEGER); +VAR + s: ARRAY 32 OF CHAR; + +BEGIN + IntToStr(x, s); + String(s) +END Int; + + +PROCEDURE trap* (modnum, _module, err, line: INTEGER); +VAR + s: ARRAY 32 OF CHAR; + +BEGIN + CASE err OF + | 1: s := "assertion failure" + | 2: s := "NIL dereference" + | 3: s := "bad divisor" + | 4: s := "NIL procedure call" + | 5: s := "type guard error" + | 6: s := "index out of range" + | 7: s := "invalid CASE" + | 8: s := "array assignment error" + | 9: s := "CHR out of range" + |10: s := "WCHR out of range" + |11: s := "BYTE out of range" + END; + + Ln; + String("error ("); Int(err); String("): "); String(s); Ln; + String("module: "); PString(_module); Ln; + String("line: "); Int(line); Ln; + + SYSTEM.CODE(0, 0, 0) (* STOP *) +END trap; + + +END Trap. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/STM32CM3/FPU.ob07 b/programs/develop/oberon07/Lib/STM32CM3/FPU.ob07 new file mode 100644 index 000000000..da30e4ea7 --- /dev/null +++ b/programs/develop/oberon07/Lib/STM32CM3/FPU.ob07 @@ -0,0 +1,465 @@ +(* + BSD 2-Clause License + + Copyright (c) 2020, Anton Krotov + All rights reserved. +*) + +MODULE FPU; + + +CONST + + INF = 07F800000H; + NINF = 0FF800000H; + NAN = 07FC00000H; + + +PROCEDURE div2 (b, a: INTEGER): INTEGER; +VAR + n, e, r, s: INTEGER; + +BEGIN + s := ORD(BITS(a) / BITS(b) - {0..30}); + e := (a DIV 800000H) MOD 256 - (b DIV 800000H) MOD 256 + 127; + + a := a MOD 800000H + 800000H; + b := b MOD 800000H + 800000H; + + n := 800000H; + r := 0; + + IF a < b THEN + a := a * 2; + DEC(e) + END; + + WHILE (a > 0) & (n > 0) DO + IF a >= b THEN + INC(r, n); + DEC(a, b) + END; + a := a * 2; + n := n DIV 2 + END; + + IF e <= 0 THEN + e := 0; + r := 800000H; + s := 0 + ELSIF e >= 255 THEN + e := 255; + r := 800000H + END + + RETURN (r - 800000H) + e * 800000H + s +END div2; + + +PROCEDURE mul2 (b, a: INTEGER): INTEGER; +VAR + e, r, s: INTEGER; + +BEGIN + s := ORD(BITS(a) / BITS(b) - {0..30}); + e := (a DIV 800000H) MOD 256 + (b DIV 800000H) MOD 256 - 127; + + a := a MOD 800000H + 800000H; + b := b MOD 800000H + 800000H; + + r := a * (b MOD 256); + b := b DIV 256; + r := LSR(r, 8); + + INC(r, a * (b MOD 256)); + b := b DIV 256; + r := LSR(r, 8); + + INC(r, a * (b MOD 256)); + r := LSR(r, 7); + + IF r >= 1000000H THEN + r := r DIV 2; + INC(e) + END; + + IF e <= 0 THEN + e := 0; + r := 800000H; + s := 0 + ELSIF e >= 255 THEN + e := 255; + r := 800000H + END + + RETURN (r - 800000H) + e * 800000H + s +END mul2; + + +PROCEDURE add2 (b, a: INTEGER): INTEGER; +VAR + ea, eb, e, d, r: INTEGER; + +BEGIN + ea := (a DIV 800000H) MOD 256; + eb := (b DIV 800000H) MOD 256; + d := ea - eb; + + a := a MOD 800000H + 800000H; + b := b MOD 800000H + 800000H; + + IF d > 0 THEN + IF d < 24 THEN + b := LSR(b, d) + ELSE + b := 0 + END; + e := ea + ELSIF d < 0 THEN + IF d > -24 THEN + a := LSR(a, -d) + ELSE + a := 0 + END; + e := eb + ELSE + e := ea + END; + + r := a + b; + + IF r >= 1000000H THEN + r := r DIV 2; + INC(e) + END; + + IF e >= 255 THEN + e := 255; + r := 800000H + END + + RETURN (r - 800000H) + e * 800000H +END add2; + + +PROCEDURE sub2 (b, a: INTEGER): INTEGER; +VAR + ea, eb, e, d, r, s: INTEGER; + +BEGIN + ea := (a DIV 800000H) MOD 256; + eb := (b DIV 800000H) MOD 256; + + a := a MOD 800000H + 800000H; + b := b MOD 800000H + 800000H; + + d := ea - eb; + + IF (d > 0) OR (d = 0) & (a >= b) THEN + s := 0 + ELSE + ea := eb; + d := -d; + r := a; + a := b; + b := r; + s := 80000000H + END; + + e := ea; + + IF d > 0 THEN + IF d < 24 THEN + b := LSR(b, d) + ELSE + b := 0 + END + END; + + r := a - b; + + IF r = 0 THEN + e := 0; + r := 800000H; + s := 0 + ELSE + WHILE r < 800000H DO + r := r * 2; + DEC(e) + END + END; + + IF e <= 0 THEN + e := 0; + r := 800000H; + s := 0 + END + + RETURN (r - 800000H) + e * 800000H + s +END sub2; + + +PROCEDURE zero (VAR x: INTEGER); +BEGIN + IF BITS(x) * {23..30} = {} THEN + x := 0 + END +END zero; + + +PROCEDURE isNaN (a: INTEGER): BOOLEAN; + RETURN (a > INF) OR (a < 0) & (a > NINF) +END isNaN; + + +PROCEDURE isInf (a: INTEGER): BOOLEAN; + RETURN (a = INF) OR (a = NINF) +END isInf; + + +PROCEDURE isNormal (a: INTEGER): BOOLEAN; + RETURN (BITS(a) * {23..30} # {23..30}) & (BITS(a) * {23..30} # {}) +END isNormal; + + +PROCEDURE add* (b, a: INTEGER): INTEGER; +VAR + r: INTEGER; + +BEGIN + zero(a); zero(b); + + IF isNormal(a) & isNormal(b) THEN + + IF (a > 0) & (b > 0) THEN + r := add2(b, a) + ELSIF (a < 0) & (b < 0) THEN + r := add2(b, a) + 80000000H + ELSIF (a > 0) & (b < 0) THEN + r := sub2(b, a) + ELSIF (a < 0) & (b > 0) THEN + r := sub2(a, b) + END + + ELSIF isNaN(a) OR isNaN(b) THEN + r := NAN + ELSIF isInf(a) & isInf(b) THEN + IF a = b THEN + r := a + ELSE + r := NAN + END + ELSIF isInf(a) THEN + r := a + ELSIF isInf(b) THEN + r := b + ELSIF a = 0 THEN + r := b + ELSIF b = 0 THEN + r := a + END + + RETURN r +END add; + + +PROCEDURE sub* (b, a: INTEGER): INTEGER; +VAR + r: INTEGER; + +BEGIN + zero(a); zero(b); + + IF isNormal(a) & isNormal(b) THEN + + IF (a > 0) & (b > 0) THEN + r := sub2(b, a) + ELSIF (a < 0) & (b < 0) THEN + r := sub2(a, b) + ELSIF (a > 0) & (b < 0) THEN + r := add2(b, a) + ELSIF (a < 0) & (b > 0) THEN + r := add2(b, a) + 80000000H + END + + ELSIF isNaN(a) OR isNaN(b) THEN + r := NAN + ELSIF isInf(a) & isInf(b) THEN + IF a # b THEN + r := a + ELSE + r := NAN + END + ELSIF isInf(a) THEN + r := a + ELSIF isInf(b) THEN + r := INF + ORD(BITS(b) / {31} - {0..30}) + ELSIF (a = 0) & (b = 0) THEN + r := 0 + ELSIF a = 0 THEN + r := ORD(BITS(b) / {31}) + ELSIF b = 0 THEN + r := a + END + + RETURN r +END sub; + + +PROCEDURE mul* (b, a: INTEGER): INTEGER; +VAR + r: INTEGER; + +BEGIN + zero(a); zero(b); + + IF isNormal(a) & isNormal(b) THEN + r := mul2(b, a) + ELSIF isNaN(a) OR isNaN(b) THEN + r := NAN + ELSIF (isInf(a) & (b = 0)) OR (isInf(b) & (a = 0)) THEN + r := NAN + ELSIF isInf(a) OR isInf(b) THEN + r := INF + ORD(BITS(a) / BITS(b) - {0..30}) + ELSIF (a = 0) OR (b = 0) THEN + r := 0 + END + + RETURN r +END mul; + + +PROCEDURE _div* (b, a: INTEGER): INTEGER; +VAR + r: INTEGER; + +BEGIN + zero(a); zero(b); + + IF isNormal(a) & isNormal(b) THEN + r := div2(b, a) + ELSIF isNaN(a) OR isNaN(b) THEN + r := NAN + ELSIF isInf(a) & isInf(b) THEN + r := NAN + ELSIF isInf(a) THEN + r := INF + ORD(BITS(a) / BITS(b) - {0..30}) + ELSIF isInf(b) THEN + r := 0 + ELSIF a = 0 THEN + IF b = 0 THEN + r := NAN + ELSE + r := 0 + END + ELSIF b = 0 THEN + IF a > 0 THEN + r := INF + ELSE + r := NINF + END + END + + RETURN r +END _div; + + +PROCEDURE cmp* (op, b, a: INTEGER): BOOLEAN; +VAR + res: BOOLEAN; + +BEGIN + zero(a); zero(b); + + IF isNaN(a) OR isNaN(b) THEN + res := op = 1 + ELSIF (a < 0) & (b < 0) THEN + CASE op OF + |0: res := a = b + |1: res := a # b + |2: res := a > b + |3: res := a >= b + |4: res := a < b + |5: res := a <= b + END + ELSE + CASE op OF + |0: res := a = b + |1: res := a # b + |2: res := a < b + |3: res := a <= b + |4: res := a > b + |5: res := a >= b + END + END + + RETURN res +END cmp; + + +PROCEDURE flt* (x: INTEGER): INTEGER; +VAR + n, y, r, s: INTEGER; + +BEGIN + IF x = 0 THEN + s := 0; + r := 800000H; + n := -126 + ELSIF x = 80000000H THEN + s := 80000000H; + r := 800000H; + n := 32 + ELSE + IF x < 0 THEN + s := 80000000H + ELSE + s := 0 + END; + n := 0; + y := ABS(x); + r := y; + WHILE y > 0 DO + y := y DIV 2; + INC(n) + END; + IF n > 24 THEN + r := LSR(r, n - 24) + ELSE + r := LSL(r, 24 - n) + END + END + + RETURN (r - 800000H) + (n + 126) * 800000H + s +END flt; + + +PROCEDURE floor* (x: INTEGER): INTEGER; +VAR + r, e: INTEGER; + +BEGIN + zero(x); + + e := (x DIV 800000H) MOD 256 - 127; + r := x MOD 800000H + 800000H; + + IF (0 <= e) & (e <= 22) THEN + r := LSR(r, 23 - e) + ORD((x < 0) & (LSL(r, e + 9) # 0)) + ELSIF (23 <= e) & (e <= 54) THEN + r := LSL(r, e - 23) + ELSIF (e < 0) & (x < 0) THEN + r := 1 + ELSE + r := 0 + END; + + IF x < 0 THEN + r := -r + END + + RETURN r +END floor; + + +END FPU. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/STM32CM3/RTL.ob07 b/programs/develop/oberon07/Lib/STM32CM3/RTL.ob07 new file mode 100644 index 000000000..255f81288 --- /dev/null +++ b/programs/develop/oberon07/Lib/STM32CM3/RTL.ob07 @@ -0,0 +1,388 @@ +(* + BSD 2-Clause License + + Copyright (c) 2019-2020, Anton Krotov + All rights reserved. +*) + +MODULE RTL; + +IMPORT SYSTEM, F := FPU; + + +CONST + + bit_depth = 32; + maxint = 7FFFFFFFH; + minint = 80000000H; + + WORD = bit_depth DIV 8; + MAX_SET = bit_depth - 1; + + +VAR + + Heap, Types, TypesCount: INTEGER; + + +PROCEDURE [code] sp (): INTEGER + 4668H; (* mov r0, sp *) + + +PROCEDURE _fmul* (b, a: INTEGER): INTEGER; + RETURN F.mul(b, a) +END _fmul; + + +PROCEDURE _fdiv* (b, a: INTEGER): INTEGER; + RETURN F._div(b, a) +END _fdiv; + + +PROCEDURE _fdivi* (b, a: INTEGER): INTEGER; + RETURN F._div(a, b) +END _fdivi; + + +PROCEDURE _fadd* (b, a: INTEGER): INTEGER; + RETURN F.add(b, a) +END _fadd; + + +PROCEDURE _fsub* (b, a: INTEGER): INTEGER; + RETURN F.sub(b, a) +END _fsub; + + +PROCEDURE _fsubi* (b, a: INTEGER): INTEGER; + RETURN F.sub(a, b) +END _fsubi; + + +PROCEDURE _fcmp* (op, b, a: INTEGER): BOOLEAN; + RETURN F.cmp(op, b, a) +END _fcmp; + + +PROCEDURE _floor* (x: INTEGER): INTEGER; + RETURN F.floor(x) +END _floor; + + +PROCEDURE _flt* (x: INTEGER): INTEGER; + RETURN F.flt(x) +END _flt; + + +PROCEDURE _pack* (n: INTEGER; VAR x: SET); +BEGIN + n := LSL((LSR(ORD(x), 23) MOD 256 + n) MOD 256, 23); + x := x - {23..30} + BITS(n) +END _pack; + + +PROCEDURE _unpk* (VAR n: INTEGER; VAR x: SET); +BEGIN + n := LSR(ORD(x), 23) MOD 256 - 127; + x := x - {30} + {23..29} +END _unpk; + + +PROCEDURE _rot* (VAR A: ARRAY OF INTEGER); +VAR + i, n, k: INTEGER; + +BEGIN + k := LEN(A) - 1; + n := A[0]; + i := 0; + WHILE i < k DO + A[i] := A[i + 1]; + INC(i) + END; + A[k] := n +END _rot; + + +PROCEDURE _set* (b, a: INTEGER): INTEGER; +BEGIN + IF (a <= b) & (a <= MAX_SET) & (b >= 0) THEN + IF b > MAX_SET THEN + b := MAX_SET + END; + IF a < 0 THEN + a := 0 + END; + a := LSR(ASR(minint, b - a), MAX_SET - b) + ELSE + a := 0 + END + + RETURN a +END _set; + + +PROCEDURE _set1* (a: INTEGER): INTEGER; +BEGIN + IF ASR(a, 5) = 0 THEN + a := LSL(1, a) + ELSE + a := 0 + END + RETURN a +END _set1; + + +PROCEDURE _length* (len, str: INTEGER): INTEGER; +VAR + c: CHAR; + res: INTEGER; + +BEGIN + res := 0; + REPEAT + SYSTEM.GET(str, c); + INC(str); + DEC(len); + INC(res) + UNTIL (len = 0) OR (c = 0X); + + RETURN res - ORD(c = 0X) +END _length; + + +PROCEDURE _move* (bytes, dest, source: INTEGER); +VAR + b: BYTE; + i: INTEGER; + +BEGIN + WHILE ((source MOD WORD # 0) OR (dest MOD WORD # 0)) & (bytes > 0) DO + SYSTEM.GET(source, b); + SYSTEM.PUT8(dest, b); + INC(source); + INC(dest); + DEC(bytes) + END; + + WHILE bytes >= WORD DO + SYSTEM.GET(source, i); + SYSTEM.PUT(dest, i); + INC(source, WORD); + INC(dest, WORD); + DEC(bytes, WORD) + END; + + WHILE bytes > 0 DO + SYSTEM.GET(source, b); + SYSTEM.PUT8(dest, b); + INC(source); + INC(dest); + DEC(bytes) + END +END _move; + + +PROCEDURE _lengthw* (len, str: INTEGER): INTEGER; +VAR + c: WCHAR; + res: INTEGER; + +BEGIN + res := 0; + REPEAT + SYSTEM.GET(str, c); + INC(str, 2); + DEC(len); + INC(res) + UNTIL (len = 0) OR (c = 0X); + + RETURN res - ORD(c = 0X) +END _lengthw; + + +PROCEDURE strncmp (a, b, n: INTEGER): INTEGER; +VAR + A, B: CHAR; + res: INTEGER; + +BEGIN + res := 0; + WHILE n > 0 DO + SYSTEM.GET(a, A); INC(a); + SYSTEM.GET(b, B); INC(b); + DEC(n); + IF A # B THEN + res := ORD(A) - ORD(B); + n := 0 + ELSIF A = 0X THEN + n := 0 + END + END + RETURN res +END strncmp; + + +PROCEDURE _strcmp* (op, len2, str2, len1, str1: INTEGER): BOOLEAN; +VAR + res: INTEGER; + bRes: BOOLEAN; + +BEGIN + res := strncmp(str1, str2, MIN(len1, len2)); + IF res = 0 THEN + res := _length(len1, str1) - _length(len2, str2) + END; + + CASE op OF + |0: bRes := res = 0 + |1: bRes := res # 0 + |2: bRes := res < 0 + |3: bRes := res <= 0 + |4: bRes := res > 0 + |5: bRes := res >= 0 + END + + RETURN bRes +END _strcmp; + + +PROCEDURE strncmpw (a, b, n: INTEGER): INTEGER; +VAR + A, B: WCHAR; + res: INTEGER; + +BEGIN + res := 0; + WHILE n > 0 DO + SYSTEM.GET(a, A); INC(a, 2); + SYSTEM.GET(b, B); INC(b, 2); + DEC(n); + IF A # B THEN + res := ORD(A) - ORD(B); + n := 0 + ELSIF A = WCHR(0) THEN + n := 0 + END + END + RETURN res +END strncmpw; + + +PROCEDURE _strcmpw* (op, len2, str2, len1, str1: INTEGER): BOOLEAN; +VAR + res: INTEGER; + bRes: BOOLEAN; + +BEGIN + res := strncmpw(str1, str2, MIN(len1, len2)); + IF res = 0 THEN + res := _lengthw(len1, str1) - _lengthw(len2, str2) + END; + + CASE op OF + |0: bRes := res = 0 + |1: bRes := res # 0 + |2: bRes := res < 0 + |3: bRes := res <= 0 + |4: bRes := res > 0 + |5: bRes := res >= 0 + END + + RETURN bRes +END _strcmpw; + + +PROCEDURE _arrcpy* (base_size, len_dst, dst, len_src, src: INTEGER): BOOLEAN; +VAR + res: BOOLEAN; + +BEGIN + IF len_src > len_dst THEN + res := FALSE + ELSE + _move(len_src * base_size, dst, src); + res := TRUE + END + + RETURN res +END _arrcpy; + + +PROCEDURE _strcpy* (chr_size, len_src, src, len_dst, dst: INTEGER); +BEGIN + _move(MIN(len_dst, len_src) * chr_size, dst, src) +END _strcpy; + + +PROCEDURE _new* (t, size: INTEGER; VAR p: INTEGER); +BEGIN + IF Heap + size < sp() - 64 THEN + p := Heap + WORD; + REPEAT + SYSTEM.PUT(Heap, t); + INC(Heap, WORD); + DEC(size, WORD); + t := 0 + UNTIL size = 0 + ELSE + p := 0 + END +END _new; + + +PROCEDURE _guard* (t, p: INTEGER): BOOLEAN; +VAR + _type: INTEGER; + +BEGIN + SYSTEM.GET(p, p); + IF p # 0 THEN + SYSTEM.GET(p - WORD, _type); + WHILE (_type # t) & (_type # 0) DO + SYSTEM.GET(Types + _type * WORD, _type) + END + ELSE + _type := t + END + + RETURN _type = t +END _guard; + + +PROCEDURE _is* (t, p: INTEGER): BOOLEAN; +VAR + _type: INTEGER; + +BEGIN + _type := 0; + IF p # 0 THEN + SYSTEM.GET(p - WORD, _type); + WHILE (_type # t) & (_type # 0) DO + SYSTEM.GET(Types + _type * WORD, _type) + END + END + + RETURN _type = t +END _is; + + +PROCEDURE _guardrec* (t0, t1: INTEGER): BOOLEAN; +BEGIN + WHILE (t1 # t0) & (t1 # 0) DO + SYSTEM.GET(Types + t1 * WORD, t1) + END + + RETURN t1 = t0 +END _guardrec; + + +PROCEDURE _init* (tcount, heap, types: INTEGER); +BEGIN + Heap := heap; + TypesCount := tcount; + Types := types +END _init; + + +END RTL. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows32/API.ob07 b/programs/develop/oberon07/Lib/Windows32/API.ob07 index 0eaf6c9a7..437d08b89 100644 --- a/programs/develop/oberon07/Lib/Windows32/API.ob07 +++ b/programs/develop/oberon07/Lib/Windows32/API.ob07 @@ -12,6 +12,8 @@ IMPORT SYSTEM; CONST + eol* = 0DX + 0AX; + SectionAlignment = 1000H; DLL_PROCESS_ATTACH = 1; @@ -19,6 +21,9 @@ CONST DLL_THREAD_DETACH = 3; DLL_PROCESS_DETACH = 0; + KERNEL = "kernel32.dll"; + USER = "user32.dll"; + TYPE @@ -27,7 +32,6 @@ TYPE VAR - eol*: ARRAY 3 OF CHAR; base*: INTEGER; heap: INTEGER; @@ -36,13 +40,12 @@ VAR thread_attach: DLL_ENTRY; -PROCEDURE [windows-, "kernel32.dll", "ExitProcess"] ExitProcess (code: INTEGER); -PROCEDURE [windows-, "kernel32.dll", "ExitThread"] ExitThread (code: INTEGER); -PROCEDURE [windows-, "kernel32.dll", "GetProcessHeap"] GetProcessHeap (): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "HeapAlloc"] HeapAlloc (hHeap, dwFlags, dwBytes: INTEGER): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "HeapFree"] HeapFree(hHeap, dwFlags, lpMem: INTEGER); - -PROCEDURE [windows-, "user32.dll", "MessageBoxA"] MessageBoxA (hWnd, lpText, lpCaption, uType: INTEGER): INTEGER; +PROCEDURE [windows-, KERNEL, ""] ExitProcess (code: INTEGER); +PROCEDURE [windows-, KERNEL, ""] ExitThread (code: INTEGER); +PROCEDURE [windows-, KERNEL, ""] GetProcessHeap (): INTEGER; +PROCEDURE [windows-, KERNEL, ""] HeapAlloc (hHeap, dwFlags, dwBytes: INTEGER): INTEGER; +PROCEDURE [windows-, KERNEL, ""] HeapFree (hHeap, dwFlags, lpMem: INTEGER); +PROCEDURE [windows-, USER, ""] MessageBoxA (hWnd, lpText, lpCaption, uType: INTEGER): INTEGER; PROCEDURE DebugMsg* (lpText, lpCaption: INTEGER); @@ -68,7 +71,6 @@ BEGIN process_detach := NIL; thread_detach := NIL; thread_attach := NIL; - eol[0] := 0DX; eol[1] := 0AX; eol[2] := 0X; base := code - SectionAlignment; heap := GetProcessHeap() END init; diff --git a/programs/develop/oberon07/Lib/Windows32/Args.ob07 b/programs/develop/oberon07/Lib/Windows32/Args.ob07 index 7777687a4..fd56e3b97 100644 --- a/programs/develop/oberon07/Lib/Windows32/Args.ob07 +++ b/programs/develop/oberon07/Lib/Windows32/Args.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2019, Anton Krotov + Copyright (c) 2019-2020, Anton Krotov All rights reserved. *) @@ -54,7 +54,7 @@ VAR BEGIN - p := WINAPI.GetCommandLine(); + p := WINAPI.GetCommandLineA(); cond := 0; count := 0; WHILE (count < MAX_PARAM) & (cond # 6) DO diff --git a/programs/develop/oberon07/Lib/Windows32/Console.ob07 b/programs/develop/oberon07/Lib/Windows32/Console.ob07 index 3cbfdb0a3..83bf0f382 100644 --- a/programs/develop/oberon07/Lib/Windows32/Console.ob07 +++ b/programs/develop/oberon07/Lib/Windows32/Console.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2019, Anton Krotov + Copyright (c) 2019-2020, Anton Krotov All rights reserved. *) @@ -48,7 +48,7 @@ VAR BEGIN WINAPI.GetConsoleScreenBufferInfo(hConsoleOutput, ScrBufInfo); fill := ORD(ScrBufInfo.dwSize.X) * ORD(ScrBufInfo.dwSize.Y); - WINAPI.FillConsoleOutputCharacter(hConsoleOutput, 20H, fill, 0, SYSTEM.ADR(fill)); + WINAPI.FillConsoleOutputCharacterA(hConsoleOutput, 20H, fill, 0, SYSTEM.ADR(fill)); WINAPI.FillConsoleOutputAttribute(hConsoleOutput, ORD(ScrBufInfo.wAttributes), fill, 0, SYSTEM.ADR(fill)); SetCursor(0, 0) END Cls; diff --git a/programs/develop/oberon07/Lib/Windows32/DateTime.ob07 b/programs/develop/oberon07/Lib/Windows32/DateTime.ob07 index 0a3173289..39bc64146 100644 --- a/programs/develop/oberon07/Lib/Windows32/DateTime.ob07 +++ b/programs/develop/oberon07/Lib/Windows32/DateTime.ob07 @@ -1,13 +1,13 @@ (* BSD 2-Clause License - Copyright (c) 2019, Anton Krotov + Copyright (c) 2019-2020, Anton Krotov All rights reserved. *) MODULE DateTime; -IMPORT WINAPI; +IMPORT WINAPI, SYSTEM; CONST @@ -116,6 +116,29 @@ BEGIN END NowEncode; +PROCEDURE NowUnixTime* (): INTEGER; + RETURN WINAPI.time(0) +END NowUnixTime; + + +PROCEDURE UnixTime* (Year, Month, Day, Hour, Min, Sec: INTEGER): INTEGER; +VAR + t: WINAPI.tm; + +BEGIN + DEC(Year, 1900); + DEC(Month); + SYSTEM.GET(SYSTEM.ADR(Sec), t.sec); + SYSTEM.GET(SYSTEM.ADR(Min), t.min); + SYSTEM.GET(SYSTEM.ADR(Hour), t.hour); + SYSTEM.GET(SYSTEM.ADR(Day), t.mday); + SYSTEM.GET(SYSTEM.ADR(Month), t.mon); + SYSTEM.GET(SYSTEM.ADR(Year), t.year); + + RETURN WINAPI.mktime(t) +END UnixTime; + + PROCEDURE init; VAR day, year, month, i: INTEGER; diff --git a/programs/develop/oberon07/Lib/Windows32/File.ob07 b/programs/develop/oberon07/Lib/Windows32/File.ob07 index 9f3470636..b02f522a8 100644 --- a/programs/develop/oberon07/Lib/Windows32/File.ob07 +++ b/programs/develop/oberon07/Lib/Windows32/File.ob07 @@ -1,13 +1,13 @@ (* BSD 2-Clause License - Copyright (c) 2019, Anton Krotov + Copyright (c) 2019-2020, Anton Krotov All rights reserved. *) MODULE File; -IMPORT SYSTEM, WINAPI; +IMPORT SYSTEM, WINAPI, API; CONST @@ -20,12 +20,14 @@ PROCEDURE Exists* (FName: ARRAY OF CHAR): BOOLEAN; VAR FindData: WINAPI.TWin32FindData; Handle: INTEGER; + attr: SET; BEGIN - Handle := WINAPI.FindFirstFile(SYSTEM.ADR(FName[0]), FindData); + Handle := WINAPI.FindFirstFileA(SYSTEM.ADR(FName[0]), FindData); IF Handle # -1 THEN WINAPI.FindClose(Handle); - IF 4 IN FindData.dwFileAttributes THEN + SYSTEM.GET32(SYSTEM.ADR(FindData.dwFileAttributes), attr); + IF 4 IN attr THEN Handle := -1 END END @@ -35,12 +37,12 @@ END Exists; PROCEDURE Delete* (FName: ARRAY OF CHAR): BOOLEAN; - RETURN WINAPI.DeleteFile(SYSTEM.ADR(FName[0])) # 0 + RETURN WINAPI.DeleteFileA(SYSTEM.ADR(FName[0])) # 0 END Delete; PROCEDURE Create* (FName: ARRAY OF CHAR): INTEGER; - RETURN WINAPI.CreateFile(SYSTEM.ADR(FName[0]), 0C0000000H, 0, NIL, 2, 80H, 0) + RETURN WINAPI.CreateFileA(SYSTEM.ADR(FName[0]), 0C0000000H, 0, NIL, 2, 80H, 0) END Create; @@ -65,13 +67,11 @@ END Seek; PROCEDURE Read* (F, Buffer, Count: INTEGER): INTEGER; VAR - res, n: INTEGER; + res: INTEGER; BEGIN - IF WINAPI.ReadFile(F, Buffer, Count, SYSTEM.ADR(n), NIL) = 0 THEN + IF WINAPI.ReadFile(F, Buffer, Count, SYSTEM.ADR(res), NIL) = 0 THEN res := -1 - ELSE - res := n END RETURN res @@ -80,13 +80,11 @@ END Read; PROCEDURE Write* (F, Buffer, Count: INTEGER): INTEGER; VAR - res, n: INTEGER; + res: INTEGER; BEGIN - IF WINAPI.WriteFile(F, Buffer, Count, SYSTEM.ADR(n), NIL) = 0 THEN + IF WINAPI.WriteFile(F, Buffer, Count, SYSTEM.ADR(res), NIL) = 0 THEN res := -1 - ELSE - res := n END RETURN res @@ -104,11 +102,10 @@ BEGIN IF F # -1 THEN Size := Seek(F, 0, SEEK_END); n := Seek(F, 0, SEEK_BEG); - res := WINAPI.GlobalAlloc(64, Size); + res := API._NEW(Size); IF (res = 0) OR (Read(F, res, Size) # Size) THEN IF res # 0 THEN - WINAPI.GlobalFree(Size); - res := 0; + res := API._DISPOSE(res); Size := 0 END END; @@ -120,7 +117,7 @@ END Load; PROCEDURE RemoveDir* (DirName: ARRAY OF CHAR): BOOLEAN; - RETURN WINAPI.RemoveDirectory(SYSTEM.ADR(DirName[0])) # 0 + RETURN WINAPI.RemoveDirectoryA(SYSTEM.ADR(DirName[0])) # 0 END RemoveDir; @@ -129,13 +126,13 @@ VAR Code: SET; BEGIN - Code := WINAPI.GetFileAttributes(SYSTEM.ADR(DirName[0])) + Code := WINAPI.GetFileAttributesA(SYSTEM.ADR(DirName[0])) RETURN (Code # {0..31}) & (4 IN Code) END ExistsDir; PROCEDURE CreateDir* (DirName: ARRAY OF CHAR): BOOLEAN; - RETURN WINAPI.CreateDirectory(SYSTEM.ADR(DirName[0]), NIL) # 0 + RETURN WINAPI.CreateDirectoryA(SYSTEM.ADR(DirName[0]), NIL) # 0 END CreateDir; diff --git a/programs/develop/oberon07/Lib/Windows32/HOST.ob07 b/programs/develop/oberon07/Lib/Windows32/HOST.ob07 index e63f9b6d7..045fce7ea 100644 --- a/programs/develop/oberon07/Lib/Windows32/HOST.ob07 +++ b/programs/develop/oberon07/Lib/Windows32/HOST.ob07 @@ -13,7 +13,7 @@ IMPORT SYSTEM, RTL; CONST slash* = "\"; - OS* = "WINDOWS"; + eol* = 0DX + 0AX; bit_depth* = RTL.bit_depth; maxint* = RTL.maxint; @@ -59,19 +59,6 @@ TYPE END; - TSystemTime = RECORD - - Year, - Month, - DayOfWeek, - Day, - Hour, - Min, - Sec, - MSec: WCHAR - - END; - VAR @@ -80,8 +67,6 @@ VAR Params: ARRAY MAX_PARAM, 2 OF INTEGER; argc: INTEGER; - eol*: ARRAY 3 OF CHAR; - maxreal*: REAL; @@ -116,12 +101,12 @@ PROCEDURE [windows-, "kernel32.dll", "OpenFile"] PROCEDURE [windows-, "kernel32.dll", "GetCurrentDirectoryA"] _GetCurrentDirectory (nBufferLength, lpBuffer: INTEGER): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "GetSystemTime"] - _GetSystemTime (T: TSystemTime); - PROCEDURE [windows-, "kernel32.dll", "ExitProcess"] _ExitProcess (code: INTEGER); +PROCEDURE [ccall, "msvcrt.dll", "time"] + _time (ptr: INTEGER): INTEGER; + PROCEDURE ExitProcess* (code: INTEGER); BEGIN @@ -215,13 +200,11 @@ END GetArg; PROCEDURE FileRead* (F: INTEGER; VAR Buffer: ARRAY OF CHAR; bytes: INTEGER): INTEGER; VAR - res, n: INTEGER; + res: INTEGER; BEGIN - IF _ReadFile(F, SYSTEM.ADR(Buffer[0]), bytes, n, NIL) = 0 THEN + IF _ReadFile(F, SYSTEM.ADR(Buffer[0]), bytes, res, NIL) = 0 THEN res := -1 - ELSE - res := n END RETURN res @@ -230,13 +213,11 @@ END FileRead; PROCEDURE FileWrite* (F: INTEGER; Buffer: ARRAY OF BYTE; bytes: INTEGER): INTEGER; VAR - res, n: INTEGER; + res: INTEGER; BEGIN - IF _WriteFile(F, SYSTEM.ADR(Buffer[0]), bytes, n, NIL) = 0 THEN + IF _WriteFile(F, SYSTEM.ADR(Buffer[0]), bytes, res, NIL) = 0 THEN res := -1 - ELSE - res := n END RETURN res @@ -269,6 +250,10 @@ BEGIN END FileOpen; +PROCEDURE chmod* (FName: ARRAY OF CHAR); +END chmod; + + PROCEDURE OutChar* (c: CHAR); VAR count: INTEGER; @@ -292,33 +277,25 @@ PROCEDURE isRelative* (path: ARRAY OF CHAR): BOOLEAN; END isRelative; -PROCEDURE now* (VAR year, month, day, hour, min, sec: INTEGER); -VAR - T: TSystemTime; - -BEGIN - _GetSystemTime(T); - year := ORD(T.Year); - month := ORD(T.Month); - day := ORD(T.Day); - hour := ORD(T.Hour); - min := ORD(T.Min); - sec := ORD(T.Sec) -END now; - - PROCEDURE UnixTime* (): INTEGER; - RETURN 0 + RETURN _time(0) END UnixTime; +PROCEDURE splitf* (x: REAL; VAR a, b: INTEGER): INTEGER; +BEGIN + SYSTEM.GET32(SYSTEM.ADR(x), a); + SYSTEM.GET32(SYSTEM.ADR(x) + 4, b) + RETURN a +END splitf; + + PROCEDURE d2s* (x: REAL): INTEGER; VAR h, l, s, e: INTEGER; BEGIN - SYSTEM.GET(SYSTEM.ADR(x), l); - SYSTEM.GET(SYSTEM.ADR(x) + 4, h); + e := splitf(x, l, h); s := ASR(h, 31) MOD 2; e := (h DIV 100000H) MOD 2048; @@ -337,7 +314,7 @@ BEGIN l := 0 ELSIF e = 2047 THEN e := 1151; - IF (h MOD 100000H # 0) OR (l # 0) THEN + IF (h MOD 100000H # 0) OR (BITS(l) * {0..31} # {}) THEN h := 80000H; l := 0 END @@ -348,22 +325,7 @@ BEGIN END d2s; -PROCEDURE splitf* (x: REAL; VAR a, b: INTEGER): INTEGER; -VAR - res: INTEGER; - BEGIN - a := 0; - b := 0; - SYSTEM.MOVE(SYSTEM.ADR(x), SYSTEM.ADR(a), 4); - SYSTEM.MOVE(SYSTEM.ADR(x) + 4, SYSTEM.ADR(b), 4); - SYSTEM.GET(SYSTEM.ADR(x), res) - RETURN res -END splitf; - - -BEGIN - eol[0] := 0DX; eol[1] := 0AX; eol[2] := 0X; maxreal := 1.9; PACK(maxreal, 1023); hConsoleOutput := _GetStdHandle(-11); diff --git a/programs/develop/oberon07/Lib/Windows32/In.ob07 b/programs/develop/oberon07/Lib/Windows32/In.ob07 index 02aa8c426..3f5cc213c 100644 --- a/programs/develop/oberon07/Lib/Windows32/In.ob07 +++ b/programs/develop/oberon07/Lib/Windows32/In.ob07 @@ -1,289 +1,80 @@ (* - Copyright 2013, 2017, 2018 Anton Krotov + BSD 2-Clause License - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . + Copyright (c) 2020, Anton Krotov + All rights reserved. *) MODULE In; -IMPORT sys := SYSTEM, WINAPI; +IMPORT SYSTEM; -TYPE - STRING = ARRAY 260 OF CHAR; +CONST + + MAX_LEN = 1024; + VAR - Done*: BOOLEAN; - hConsoleInput: INTEGER; + Done*: BOOLEAN; + hConsoleInput: INTEGER; + s: ARRAY MAX_LEN + 4 OF CHAR; -PROCEDURE digit(ch: CHAR): BOOLEAN; - RETURN (ch >= "0") & (ch <= "9") -END digit; -PROCEDURE CheckInt(s: STRING; VAR first, last: INTEGER; VAR neg: BOOLEAN; Point: BOOLEAN): BOOLEAN; -VAR i: INTEGER; +PROCEDURE [ccall, "msvcrt.dll", ""] sscanf (buf: INTEGER; fmt: INTEGER; adr: INTEGER): INTEGER; +PROCEDURE [windows, "kernel32.dll", ""] GetStdHandle (nStdHandle: INTEGER): INTEGER; +PROCEDURE [windows, "kernel32.dll", ""] ReadConsoleA (hConsoleInput, lpBuffer, nNumberOfCharsToRead, lpNumberOfCharsRead, lpReserved: INTEGER); + + +PROCEDURE String* (VAR str: ARRAY OF CHAR); +VAR + count: INTEGER; + BEGIN - i := 0; - neg := FALSE; - WHILE (s[i] <= 20X) & (s[i] # 0X) DO - INC(i) - END; - IF s[i] = "-" THEN - neg := TRUE; - INC(i) - ELSIF s[i] = "+" THEN - INC(i) - END; - first := i; - WHILE digit(s[i]) DO - INC(i) - END; - last := i - RETURN ((s[i] <= 20X) OR (Point & (s[i] = "."))) & digit(s[first]) -END CheckInt; - -PROCEDURE IsMinInt(str: STRING; pos: INTEGER): BOOLEAN; -VAR i: INTEGER; min: STRING; -BEGIN - i := 0; - min := "2147483648"; - WHILE (min[i] # 0X) & (str[i] # 0X) & (min[i] = str[i + pos]) DO - INC(i) - END - RETURN i = 10 -END IsMinInt; - -PROCEDURE StrToInt(str: STRING; VAR err: BOOLEAN): INTEGER; -CONST maxINT = 7FFFFFFFH; -VAR i, n, res: INTEGER; flag, neg: BOOLEAN; -BEGIN - res := 0; - flag := CheckInt(str, i, n, neg, FALSE); - err := ~flag; - IF flag & neg & IsMinInt(str, i) THEN - flag := FALSE; - neg := FALSE; - res := 80000000H - END; - WHILE flag & digit(str[i]) DO - IF res > maxINT DIV 10 THEN - err := TRUE; - flag := FALSE; - res := 0 - ELSE - res := res * 10; - IF res > maxINT - (ORD(str[i]) - ORD("0")) THEN - err := TRUE; - flag := FALSE; - res := 0 - ELSE - res := res + (ORD(str[i]) - ORD("0")); - INC(i) - END - END - END; - IF neg THEN - res := -res - END - RETURN res -END StrToInt; - -PROCEDURE Space(s: STRING): BOOLEAN; -VAR i: INTEGER; -BEGIN - i := 0; - WHILE (s[i] # 0X) & (s[i] <= 20X) DO - INC(i) - END - RETURN s[i] = 0X -END Space; - -PROCEDURE CheckReal(s: STRING; VAR n: INTEGER; VAR neg: BOOLEAN): BOOLEAN; -VAR i: INTEGER; Res: BOOLEAN; -BEGIN - Res := CheckInt(s, n, i, neg, TRUE); - IF Res THEN - IF s[i] = "." THEN - INC(i); - WHILE digit(s[i]) DO - INC(i) - END; - IF (s[i] = "D") OR (s[i] = "E") OR (s[i] = "d") OR (s[i] = "e") THEN - INC(i); - IF (s[i] = "+") OR (s[i] = "-") THEN - INC(i) - END; - Res := digit(s[i]); - WHILE digit(s[i]) DO - INC(i) - END - END - END - END - RETURN Res & (s[i] <= 20X) -END CheckReal; - -PROCEDURE StrToFloat(str: STRING; VAR err: BOOLEAN): REAL; -CONST maxDBL = 1.69E308; maxINT = 7FFFFFFFH; -VAR i, scale: INTEGER; res, m, d: REAL; minus, neg: BOOLEAN; - - PROCEDURE part1(VAR res, d: REAL; VAR i: INTEGER; str: STRING): BOOLEAN; - BEGIN - res := 0.0; - d := 1.0; - WHILE digit(str[i]) DO - res := res * 10.0 + FLT(ORD(str[i]) - ORD("0")); - INC(i) + ReadConsoleA(hConsoleInput, SYSTEM.ADR(s[0]), MAX_LEN, SYSTEM.ADR(count), 0); + IF (s[count - 1] = 0AX) & (s[count - 2] = 0DX) THEN + DEC(count, 2) END; - IF str[i] = "." THEN - INC(i); - WHILE digit(str[i]) DO - d := d / 10.0; - res := res + FLT(ORD(str[i]) - ORD("0")) * d; - INC(i) - END - END - RETURN str[i] # 0X - END part1; - - PROCEDURE part2(VAR i, scale: INTEGER; VAR m, res: REAL; VAR minus, err: BOOLEAN; str: STRING): BOOLEAN; - BEGIN - INC(i); - m := 10.0; - minus := FALSE; - IF str[i] = "+" THEN - INC(i) - ELSIF str[i] = "-" THEN - minus := TRUE; - INC(i); - m := 0.1 - END; - scale := 0; - err := FALSE; - WHILE ~err & digit(str[i]) DO - IF scale > maxINT DIV 10 THEN - err := TRUE; - res := 0.0 - ELSE - scale := scale * 10; - IF scale > maxINT - (ORD(str[i]) - ORD("0")) THEN - err := TRUE; - res := 0.0 - ELSE - scale := scale + (ORD(str[i]) - ORD("0")); - INC(i) - END - END - END - RETURN ~err - END part2; - - PROCEDURE part3 (VAR err, minus: BOOLEAN; VAR scale: INTEGER; VAR res, m: REAL); - VAR i: INTEGER; - BEGIN - err := FALSE; - IF scale = maxINT THEN - err := TRUE; - res := 0.0 - END; - i := 1; - WHILE ~err & (i <= scale) DO - IF ~minus & (res > maxDBL / m) THEN - err := TRUE; - res := 0.0 - ELSE - res := res * m; - INC(i) - END - END - END part3; - -BEGIN - IF CheckReal(str, i, neg) THEN - IF part1(res, d, i, str) & part2(i, scale, m, res, minus, err, str) THEN - part3(err, minus, scale, res, m) - END; - IF neg THEN - res := -res - END - ELSE - res := 0.0; - err := TRUE - END - RETURN res -END StrToFloat; - -PROCEDURE String*(VAR s: ARRAY OF CHAR); -VAR count, i: INTEGER; str: STRING; -BEGIN - WINAPI.ReadConsole(hConsoleInput, sys.ADR(str[0]), 256, sys.ADR(count), 0); - IF (str[count - 1] = 0AX) & (str[count - 2] = 0DX) THEN - DEC(count, 2) - END; - str[256] := 0X; - str[count] := 0X; - i := 0; - WHILE (i < LEN(s) - 1) & (i < LEN(str)) & (str[i] # 0X) DO - s[i] := str[i]; - INC(i) - END; - s[i] := 0X; - Done := TRUE + s[count] := 0X; + COPY(s, str); + str[LEN(str) - 1] := 0X; + Done := TRUE END String; -PROCEDURE Char*(VAR x: CHAR); -VAR str: STRING; -BEGIN - String(str); - x := str[0]; - Done := TRUE -END Char; -PROCEDURE Ln*; -VAR str: STRING; +PROCEDURE Int* (VAR x: INTEGER); BEGIN - String(str); - Done := TRUE -END Ln; + String(s); + Done := sscanf(SYSTEM.ADR(s[0]), SYSTEM.SADR("%d"), SYSTEM.ADR(x)) = 1 +END Int; -PROCEDURE Real*(VAR x: REAL); -VAR str: STRING; err: BOOLEAN; + +PROCEDURE Real* (VAR x: REAL); BEGIN - err := FALSE; - REPEAT - String(str) - UNTIL ~Space(str); - x := StrToFloat(str, err); - Done := ~err + String(s); + Done := sscanf(SYSTEM.ADR(s[0]), SYSTEM.SADR("%lf"), SYSTEM.ADR(x)) = 1 END Real; -PROCEDURE Int*(VAR x: INTEGER); -VAR str: STRING; err: BOOLEAN; + +PROCEDURE Char* (VAR x: CHAR); BEGIN - err := FALSE; - REPEAT - String(str) - UNTIL ~Space(str); - x := StrToInt(str, err); - Done := ~err -END Int; + String(s); + x := s[0] +END Char; + + +PROCEDURE Ln*; +BEGIN + String(s) +END Ln; + PROCEDURE Open*; BEGIN - hConsoleInput := WINAPI.GetStdHandle(-10); - Done := TRUE + hConsoleInput := GetStdHandle(-10); + Done := TRUE END Open; + END In. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows32/Math.ob07 b/programs/develop/oberon07/Lib/Windows32/Math.ob07 index b1fe62acc..d6056af74 100644 --- a/programs/develop/oberon07/Lib/Windows32/Math.ob07 +++ b/programs/develop/oberon07/Lib/Windows32/Math.ob07 @@ -1,18 +1,8 @@ (* - Copyright 2013, 2014, 2018, 2019 Anton Krotov + BSD 2-Clause License - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . + Copyright (c) 2013-2014, 2018-2020 Anton Krotov + All rights reserved. *) MODULE Math; @@ -235,6 +225,16 @@ BEGIN END frac; +PROCEDURE sqri* (x: INTEGER): INTEGER; + RETURN x * x +END sqri; + + +PROCEDURE sqrr* (x: REAL): REAL; + RETURN x * x +END sqrr; + + PROCEDURE arcsin* (x: REAL): REAL; RETURN arctan2(x, sqrt(1.0 - x * x)) END arcsin; @@ -349,6 +349,40 @@ BEGIN END power; +PROCEDURE ipower* (base: REAL; exponent: INTEGER): REAL; +VAR + i: INTEGER; + a: REAL; + +BEGIN + a := 1.0; + + IF base # 0.0 THEN + IF exponent # 0 THEN + IF exponent < 0 THEN + base := 1.0 / base + END; + i := ABS(exponent); + WHILE i > 0 DO + WHILE ~ODD(i) DO + i := LSR(i, 1); + base := sqrr(base) + END; + DEC(i); + a := a * base + END + ELSE + a := 1.0 + END + ELSE + ASSERT(exponent > 0); + a := 0.0 + END + + RETURN a +END ipower; + + PROCEDURE sgn* (x: REAL): INTEGER; VAR res: INTEGER; @@ -381,4 +415,36 @@ BEGIN END fact; +PROCEDURE DegToRad* (x: REAL): REAL; + RETURN x * (pi / 180.0) +END DegToRad; + + +PROCEDURE RadToDeg* (x: REAL): REAL; + RETURN x * (180.0 / pi) +END RadToDeg; + + +(* Return hypotenuse of triangle *) +PROCEDURE hypot* (x, y: REAL): REAL; +VAR + a: REAL; + +BEGIN + x := ABS(x); + y := ABS(y); + IF x > y THEN + a := x * sqrt(1.0 + sqrr(y / x)) + ELSE + IF x > 0.0 THEN + a := y * sqrt(1.0 + sqrr(x / y)) + ELSE + a := y + END + END + + RETURN a +END hypot; + + END Math. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows32/Out.ob07 b/programs/develop/oberon07/Lib/Windows32/Out.ob07 index 6e6950c00..779527492 100644 --- a/programs/develop/oberon07/Lib/Windows32/Out.ob07 +++ b/programs/develop/oberon07/Lib/Windows32/Out.ob07 @@ -1,280 +1,77 @@ (* - Copyright 2013, 2014, 2017, 2018 Anton Krotov + BSD 2-Clause License - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . + Copyright (c) 2020, Anton Krotov + All rights reserved. *) MODULE Out; -IMPORT sys := SYSTEM, WINAPI; +IMPORT SYSTEM; -CONST - - d = 1.0 - 5.0E-12; VAR - hConsoleOutput: INTEGER; - Realp: PROCEDURE (x: REAL; width: INTEGER); + hConsoleOutput: INTEGER; -PROCEDURE String*(s: ARRAY OF CHAR); -VAR count: INTEGER; +PROCEDURE [ccall, "msvcrt.dll", "printf"] printf1 (fmt: INTEGER; x: INTEGER); +PROCEDURE [ccall, "msvcrt.dll", "printf"] printf2 (fmt: INTEGER; width, x: INTEGER); +PROCEDURE [ccall, "msvcrt.dll", "printf"] printf3 (fmt: INTEGER; width, precision: INTEGER; x: REAL); + +PROCEDURE [windows, "kernel32.dll", ""] + WriteConsoleW (hConsoleOutput, lpBuffer, nNumberOfCharsToWrite, lpNumberOfCharsWritten, lpReserved: INTEGER); + +PROCEDURE [windows, "kernel32.dll", ""] + GetStdHandle (nStdHandle: INTEGER): INTEGER; + + +PROCEDURE Char* (x: CHAR); BEGIN - WINAPI.WriteFile(hConsoleOutput, sys.ADR(s[0]), LENGTH(s), sys.ADR(count), NIL) -END String; - -PROCEDURE StringW*(s: ARRAY OF WCHAR); -VAR count: INTEGER; -BEGIN - WINAPI.WriteConsoleW(hConsoleOutput, sys.ADR(s[0]), LENGTH(s), sys.ADR(count), 0) -END StringW; - -PROCEDURE Char*(x: CHAR); -VAR count: INTEGER; -BEGIN - WINAPI.WriteFile(hConsoleOutput, sys.ADR(x), 1, sys.ADR(count), NIL) + printf1(SYSTEM.SADR("%c"), ORD(x)) END Char; -PROCEDURE WriteInt(x, n: INTEGER); -VAR i: INTEGER; a: ARRAY 16 OF CHAR; neg: BOOLEAN; -BEGIN - i := 0; - IF n < 1 THEN - n := 1 - END; - IF x < 0 THEN - x := -x; - DEC(n); - neg := TRUE - END; - REPEAT - a[i] := CHR(x MOD 10 + ORD("0")); - x := x DIV 10; - INC(i) - UNTIL x = 0; - WHILE n > i DO - Char(" "); - DEC(n) - END; - IF neg THEN - Char("-") - END; - REPEAT - DEC(i); - Char(a[i]) - UNTIL i = 0 -END WriteInt; -PROCEDURE IsNan(AValue: REAL): BOOLEAN; -VAR h, l: SET; +PROCEDURE StringW* (s: ARRAY OF WCHAR); BEGIN - sys.GET(sys.ADR(AValue), l); - sys.GET(sys.ADR(AValue) + 4, h) - RETURN (h * {20..30} = {20..30}) & ((h * {0..19} # {}) OR (l * {0..31} # {})) -END IsNan; + WriteConsoleW(hConsoleOutput, SYSTEM.ADR(s[0]), LENGTH(s), 0, 0) +END StringW; -PROCEDURE IsInf(x: REAL): BOOLEAN; - RETURN ABS(x) = sys.INF() -END IsInf; -PROCEDURE Int*(x, width: INTEGER); -VAR i: INTEGER; +PROCEDURE String* (s: ARRAY OF CHAR); BEGIN - IF x # 80000000H THEN - WriteInt(x, width) - ELSE - FOR i := 12 TO width DO - Char(20X) - END; - String("-2147483648") - END -END Int; + printf2(SYSTEM.SADR("%.*s"), LENGTH(s), SYSTEM.ADR(s[0])) +END String; -PROCEDURE OutInf(x: REAL; width: INTEGER); -VAR s: ARRAY 5 OF CHAR; i: INTEGER; -BEGIN - IF IsNan(x) THEN - s := "Nan"; - INC(width) - ELSIF IsInf(x) & (x > 0.0) THEN - s := "+Inf" - ELSIF IsInf(x) & (x < 0.0) THEN - s := "-Inf" - END; - FOR i := 1 TO width - 4 DO - Char(" ") - END; - String(s) -END OutInf; PROCEDURE Ln*; BEGIN - Char(0DX); - Char(0AX) + printf1(SYSTEM.SADR("%s"), SYSTEM.SADR(CHR(13) + CHR(10))) END Ln; -PROCEDURE _FixReal(x: REAL; width, p: INTEGER); -VAR e, len, i: INTEGER; y: REAL; minus: BOOLEAN; -BEGIN - IF IsNan(x) OR IsInf(x) THEN - OutInf(x, width) - ELSIF p < 0 THEN - Realp(x, width) - ELSE - len := 0; - minus := FALSE; - IF x < 0.0 THEN - minus := TRUE; - INC(len); - x := ABS(x) - END; - e := 0; - WHILE x >= 10.0 DO - x := x / 10.0; - INC(e) - END; - IF e >= 0 THEN - len := len + e + p + 1; - IF x > 9.0 + d THEN - INC(len) - END; - IF p > 0 THEN - INC(len) - END; - ELSE - len := len + p + 2 - END; - FOR i := 1 TO width - len DO - Char(" ") - END; - IF minus THEN - Char("-") - END; - y := x; - WHILE (y < 1.0) & (y # 0.0) DO - y := y * 10.0; - DEC(e) - END; - IF e < 0 THEN - IF x - FLT(FLOOR(x)) > d THEN - Char("1"); - x := 0.0 - ELSE - Char("0"); - x := x * 10.0 - END - ELSE - WHILE e >= 0 DO - IF x - FLT(FLOOR(x)) > d THEN - IF x > 9.0 THEN - String("10") - ELSE - Char(CHR(FLOOR(x) + ORD("0") + 1)) - END; - x := 0.0 - ELSE - Char(CHR(FLOOR(x) + ORD("0"))); - x := (x - FLT(FLOOR(x))) * 10.0 - END; - DEC(e) - END - END; - IF p > 0 THEN - Char(".") - END; - WHILE p > 0 DO - IF x - FLT(FLOOR(x)) > d THEN - Char(CHR(FLOOR(x) + ORD("0") + 1)); - x := 0.0 - ELSE - Char(CHR(FLOOR(x) + ORD("0"))); - x := (x - FLT(FLOOR(x))) * 10.0 - END; - DEC(p) - END - END -END _FixReal; - -PROCEDURE Real*(x: REAL; width: INTEGER); -VAR e, n, i: INTEGER; minus: BOOLEAN; +PROCEDURE Int* (x, width: INTEGER); BEGIN - Realp := Real; - IF IsNan(x) OR IsInf(x) THEN - OutInf(x, width) - ELSE - e := 0; - n := 0; - IF width > 23 THEN - n := width - 23; - width := 23 - ELSIF width < 9 THEN - width := 9 - END; - width := width - 5; - IF x < 0.0 THEN - x := -x; - minus := TRUE - ELSE - minus := FALSE - END; - WHILE x >= 10.0 DO - x := x / 10.0; - INC(e) - END; - WHILE (x < 1.0) & (x # 0.0) DO - x := x * 10.0; - DEC(e) - END; - IF x > 9.0 + d THEN - x := 1.0; - INC(e) - END; - FOR i := 1 TO n DO - Char(" ") - END; - IF minus THEN - x := -x - END; - _FixReal(x, width, width - 3); - Char("E"); - IF e >= 0 THEN - Char("+") - ELSE - Char("-"); - e := ABS(e) - END; - IF e < 100 THEN - Char("0") - END; - IF e < 10 THEN - Char("0") - END; - Int(e, 0) - END + printf2(SYSTEM.SADR("%*d"), width, x) +END Int; + + +PROCEDURE Real* (x: REAL; width: INTEGER); +BEGIN + printf3(SYSTEM.SADR("%*.*E"), width, MAX(MIN(width - 8, 15), 1), x) END Real; -PROCEDURE FixReal*(x: REAL; width, p: INTEGER); + +PROCEDURE FixReal* (x: REAL; width, precision: INTEGER); BEGIN - Realp := Real; - _FixReal(x, width, p) + printf3(SYSTEM.SADR("%*.*f"), width, precision, x) END FixReal; + PROCEDURE Open*; BEGIN - hConsoleOutput := WINAPI.GetStdHandle(-11) + hConsoleOutput := GetStdHandle(-11) END Open; + END Out. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows32/RTL.ob07 b/programs/develop/oberon07/Lib/Windows32/RTL.ob07 index 0929a5678..5f9e16808 100644 --- a/programs/develop/oberon07/Lib/Windows32/RTL.ob07 +++ b/programs/develop/oberon07/Lib/Windows32/RTL.ob07 @@ -372,33 +372,29 @@ END PCharToStr; PROCEDURE IntToStr (x: INTEGER; VAR str: ARRAY OF CHAR); VAR - i, a, b: INTEGER; - c: CHAR; + i, a: INTEGER; BEGIN i := 0; + a := x; REPEAT - str[i] := CHR(x MOD 10 + ORD("0")); - x := x DIV 10; - INC(i) - UNTIL x = 0; + INC(i); + a := a DIV 10 + UNTIL a = 0; - a := 0; - b := i - 1; - WHILE a < b DO - c := str[a]; - str[a] := str[b]; - str[b] := c; - INC(a); - DEC(b) - END; - str[i] := 0X + str[i] := 0X; + + REPEAT + DEC(i); + str[i] := CHR(x MOD 10 + ORD("0")); + x := x DIV 10 + UNTIL x = 0 END IntToStr; PROCEDURE append (VAR s1: ARRAY OF CHAR; s2: ARRAY OF CHAR); VAR - n1, n2, i, j: INTEGER; + n1, n2: INTEGER; BEGIN n1 := LENGTH(s1); @@ -406,19 +402,12 @@ BEGIN ASSERT(n1 + n2 < LEN(s1)); - i := 0; - j := n1; - WHILE i < n2 DO - s1[j] := s2[i]; - INC(i); - INC(j) - END; - - s1[j] := 0X + SYSTEM.MOVE(SYSTEM.ADR(s2[0]), SYSTEM.ADR(s1[n1]), n2); + s1[n1 + n2] := 0X END append; -PROCEDURE [stdcall] _error* (module, err, line: INTEGER); +PROCEDURE [stdcall] _error* (modnum, _module, err, line: INTEGER); VAR s, temp: ARRAY 1024 OF CHAR; @@ -437,10 +426,8 @@ BEGIN |11: s := "BYTE out of range" END; - append(s, API.eol); - - append(s, "module: "); PCharToStr(module, temp); append(s, temp); append(s, API.eol); - append(s, "line: "); IntToStr(line, temp); append(s, temp); + append(s, API.eol + "module: "); PCharToStr(_module, temp); append(s, temp); + append(s, API.eol + "line: "); IntToStr(line, temp); append(s, temp); API.DebugMsg(SYSTEM.ADR(s[0]), name); diff --git a/programs/develop/oberon07/Lib/Windows32/UnixTime.ob07 b/programs/develop/oberon07/Lib/Windows32/UnixTime.ob07 deleted file mode 100644 index 0e6ed5bd6..000000000 --- a/programs/develop/oberon07/Lib/Windows32/UnixTime.ob07 +++ /dev/null @@ -1,64 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2019, Anton Krotov - All rights reserved. -*) - -MODULE UnixTime; - - -VAR - - days: ARRAY 12, 31, 2 OF INTEGER; - - -PROCEDURE init; -VAR - i, j, k, n0, n1: INTEGER; -BEGIN - - FOR i := 0 TO 11 DO - FOR j := 0 TO 30 DO - days[i, j, 0] := 0; - days[i, j, 1] := 0; - END - END; - - days[ 1, 28, 0] := -1; - - FOR k := 0 TO 1 DO - days[ 1, 29, k] := -1; - days[ 1, 30, k] := -1; - days[ 3, 30, k] := -1; - days[ 5, 30, k] := -1; - days[ 8, 30, k] := -1; - days[10, 30, k] := -1; - END; - - n0 := 0; - n1 := 0; - FOR i := 0 TO 11 DO - FOR j := 0 TO 30 DO - IF days[i, j, 0] = 0 THEN - days[i, j, 0] := n0; - INC(n0) - END; - IF days[i, j, 1] = 0 THEN - days[i, j, 1] := n1; - INC(n1) - END - END - END - -END init; - - -PROCEDURE time* (year, month, day, hour, min, sec: INTEGER): INTEGER; - RETURN ((year - 1970) * 365 + days[month - 1, day - 1, ORD(year DIV 4 = 0)] + (year - 1969) DIV 4) * 86400 + hour * 3600 + min * 60 + sec -END time; - - -BEGIN - init -END UnixTime. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows32/Utils.ob07 b/programs/develop/oberon07/Lib/Windows32/Utils.ob07 deleted file mode 100644 index 0f85e9808..000000000 --- a/programs/develop/oberon07/Lib/Windows32/Utils.ob07 +++ /dev/null @@ -1,76 +0,0 @@ -(* - Copyright 2013, 2017, 2018, 2020 Anton Krotov - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*) - -MODULE Utils; - -IMPORT WINAPI; - -PROCEDURE PutSeed*(seed: INTEGER); -BEGIN - WINAPI.srand(seed) -END PutSeed; - -PROCEDURE Rnd*(range : INTEGER): INTEGER; - RETURN WINAPI.rand() MOD range -END Rnd; - -PROCEDURE Utf8To16*(source: ARRAY OF CHAR; VAR dest: ARRAY OF CHAR): INTEGER; -VAR i, j, L, u, N: INTEGER; -BEGIN - L := LEN(source); - N := LEN(dest); - N := N - N MOD 2 - 1; - i := 0; - j := 0; - WHILE (i < L) & (j < N) & (source[i] # 0X) DO - CASE source[i] OF - |00X..7FX: u := ORD(source[i]); - |0C1X..0DFX: - u := LSL(ORD(source[i]) - 0C0H, 6); - IF i + 1 < L THEN - u := u + ROR(LSL(ORD(source[i + 1]), 26), 26); - INC(i) - END - |0E1X..0EFX: - u := LSL(ORD(source[i]) - 0E0H, 12); - IF i + 1 < L THEN - u := u + ROR(LSL(ORD(source[i + 1]), 26), 20); - INC(i) - END; - IF i + 1 < L THEN - u := u + ROR(LSL(ORD(source[i + 1]), 26), 26); - INC(i) - END -(* |0F1X..0F7X: - |0F9X..0FBX: - |0FDX:*) - ELSE - END; - INC(i); - dest[j] := CHR(u MOD 256); - INC(j); - dest[j] := CHR(u DIV 256); - INC(j); - END; - IF j < N THEN - dest[j] := 0X; - dest[j + 1] := 0X - END - RETURN j DIV 2 -END Utf8To16; - -END Utils. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows32/WINAPI.ob07 b/programs/develop/oberon07/Lib/Windows32/WINAPI.ob07 index f6043431a..1fe4efabc 100644 --- a/programs/develop/oberon07/Lib/Windows32/WINAPI.ob07 +++ b/programs/develop/oberon07/Lib/Windows32/WINAPI.ob07 @@ -14,6 +14,10 @@ CONST OFS_MAXPATHNAME* = 128; + KERNEL = "kernel32.dll"; + USER = "user32.dll"; + MSVCRT = "msvcrt.dll"; + TYPE @@ -56,42 +60,59 @@ TYPE END; + tm* = RECORD + + sec*, + min*, + hour*, + mday*, + mon*, + year*, + wday*, + yday*, + isdst*: SYSTEM.CARD32 + + END; + PSecurityAttributes* = POINTER TO TSecurityAttributes; TSecurityAttributes* = RECORD - nLength*: INTEGER; + nLength*: SYSTEM.CARD32; lpSecurityDescriptor*: INTEGER; - bInheritHandle*: INTEGER + bInheritHandle*: SYSTEM.CARD32 (* BOOL *) END; TFileTime* = RECORD dwLowDateTime*, - dwHighDateTime*: INTEGER + dwHighDateTime*: SYSTEM.CARD32 END; TWin32FindData* = RECORD - dwFileAttributes*: SET; + dwFileAttributes*: SYSTEM.CARD32; ftCreationTime*: TFileTime; ftLastAccessTime*: TFileTime; ftLastWriteTime*: TFileTime; - nFileSizeHigh*: INTEGER; - nFileSizeLow*: INTEGER; - dwReserved0*: INTEGER; - dwReserved1*: INTEGER; + nFileSizeHigh*: SYSTEM.CARD32; + nFileSizeLow*: SYSTEM.CARD32; + dwReserved0*: SYSTEM.CARD32; + dwReserved1*: SYSTEM.CARD32; cFileName*: STRING; - cAlternateFileName*: ARRAY 14 OF CHAR + cAlternateFileName*: ARRAY 14 OF CHAR; + dwFileType*: SYSTEM.CARD32; + dwCreatorType*: SYSTEM.CARD32; + wFinderFlags*: WCHAR END; OFSTRUCT* = RECORD - cBytes*: CHAR; - fFixedDisk*: CHAR; + cBytes*: BYTE; + fFixedDisk*: BYTE; nErrCode*: WCHAR; Reserved1*: WCHAR; Reserved2*: WCHAR; @@ -105,131 +126,93 @@ TYPE Internal*: INTEGER; InternalHigh*: INTEGER; - Offset*: INTEGER; - OffsetHigh*: INTEGER; + Offset*: SYSTEM.CARD32; + OffsetHigh*: SYSTEM.CARD32; hEvent*: INTEGER END; -PROCEDURE [windows-, "kernel32.dll", "SetConsoleCursorPosition"] - SetConsoleCursorPosition* (hConsoleOutput, dwCursorPosition: INTEGER): INTEGER; +PROCEDURE [windows-, KERNEL, ""] SetConsoleCursorPosition* (hConsoleOutput, dwCursorPosition: INTEGER): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "GetConsoleScreenBufferInfo"] - GetConsoleScreenBufferInfo* (hConsoleOutput: INTEGER; ConsoleScreenBufferInfo: TConsoleScreenBufferInfo): INTEGER; +PROCEDURE [windows-, KERNEL, ""] GetConsoleScreenBufferInfo* (hConsoleOutput: INTEGER; ConsoleScreenBufferInfo: TConsoleScreenBufferInfo): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "FillConsoleOutputCharacterA"] - FillConsoleOutputCharacter* (hConsoleOutput, cCaracter, nLength, dwWriteCoord, lpNumberOfCharsWritten: INTEGER): INTEGER; +PROCEDURE [windows-, KERNEL, ""] FillConsoleOutputCharacterA* (hConsoleOutput, cCaracter, nLength, dwWriteCoord, lpNumberOfCharsWritten: INTEGER): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "FillConsoleOutputAttribute"] - FillConsoleOutputAttribute* (hConsoleOutput, wAttribute, nLength, dwWriteCoord, lpNumberOfAttrsWritten: INTEGER): INTEGER; +PROCEDURE [windows-, KERNEL, ""] FillConsoleOutputAttribute* (hConsoleOutput, wAttribute, nLength, dwWriteCoord, lpNumberOfAttrsWritten: INTEGER): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "SetConsoleTextAttribute"] - SetConsoleTextAttribute* (hConsoleOutput, wAttributes: INTEGER): INTEGER; +PROCEDURE [windows-, KERNEL, ""] SetConsoleTextAttribute* (hConsoleOutput, wAttributes: INTEGER): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "GetStdHandle"] - GetStdHandle* (nStdHandle: INTEGER): INTEGER; +PROCEDURE [windows-, KERNEL, ""] GetStdHandle* (nStdHandle: INTEGER): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "GetLocalTime"] - GetLocalTime* (T: TSystemTime); +PROCEDURE [windows-, KERNEL, ""] GetLocalTime* (T: TSystemTime); -PROCEDURE [windows-, "kernel32.dll", "RemoveDirectoryA"] - RemoveDirectory* (lpPathName: INTEGER): INTEGER; +PROCEDURE [windows-, KERNEL, ""] RemoveDirectoryA* (lpPathName: INTEGER): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "GetFileAttributesA"] - GetFileAttributes* (lpPathName: INTEGER): SET; +PROCEDURE [windows-, KERNEL, ""] GetFileAttributesA* (lpPathName: INTEGER): SET; -PROCEDURE [windows-, "kernel32.dll", "CreateDirectoryA"] - CreateDirectory* (lpPathName: INTEGER; lpSecurityAttributes: PSecurityAttributes): INTEGER; +PROCEDURE [windows-, KERNEL, ""] CreateDirectoryA* (lpPathName: INTEGER; lpSecurityAttributes: PSecurityAttributes): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "FindFirstFileA"] - FindFirstFile* (lpFileName: INTEGER; lpFindFileData: TWin32FindData): INTEGER; +PROCEDURE [windows-, KERNEL, ""] FindFirstFileA* (lpFileName: INTEGER; lpFindFileData: TWin32FindData): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "DeleteFileA"] - DeleteFile* (lpFileName: INTEGER): INTEGER; +PROCEDURE [windows-, KERNEL, ""] DeleteFileA* (lpFileName: INTEGER): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "FindClose"] - FindClose* (hFindFile: INTEGER): INTEGER; +PROCEDURE [windows-, KERNEL, ""] FindClose* (hFindFile: INTEGER): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "CloseHandle"] - CloseHandle* (hObject: INTEGER): INTEGER; +PROCEDURE [windows-, KERNEL, ""] CloseHandle* (hObject: INTEGER): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "CreateFileA"] - CreateFile* ( +PROCEDURE [windows-, KERNEL, ""] CreateFileA* ( lpFileName, dwDesiredAccess, dwShareMode: INTEGER; lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile: INTEGER): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "OpenFile"] - OpenFile* (lpFileName: INTEGER; lpReOpenBuff: OFSTRUCT; uStyle: INTEGER): INTEGER; +PROCEDURE [windows-, KERNEL, ""] OpenFile* (lpFileName: INTEGER; lpReOpenBuff: OFSTRUCT; uStyle: INTEGER): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "SetFilePointer"] - SetFilePointer* (hFile, lDistanceToMove, lpDistanceToMoveHigh, dwMoveMethod: INTEGER): INTEGER; +PROCEDURE [windows-, KERNEL, ""] SetFilePointer* (hFile, lDistanceToMove, lpDistanceToMoveHigh, dwMoveMethod: INTEGER): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "ReadFile"] - ReadFile* (hFile, Buffer, nNumberOfBytesToRead, lpNumberOfBytesRead: INTEGER; lpOverlapped: POverlapped): INTEGER; +PROCEDURE [windows-, KERNEL, ""] ReadFile* (hFile, Buffer, nNumberOfBytesToRead, lpNumberOfBytesRead: INTEGER; lpOverlapped: POverlapped): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "WriteFile"] - WriteFile* (hFile, Buffer, nNumberOfBytesToRead, lpNumberOfBytesRead: INTEGER; lpOverlapped: POverlapped): INTEGER; +PROCEDURE [windows-, KERNEL, ""] WriteFile* (hFile, Buffer, nNumberOfBytesToRead, lpNumberOfBytesRead: INTEGER; lpOverlapped: POverlapped): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "ReadConsoleA"] - ReadConsole* (hConsoleInput, lpBuffer, nNumberOfCharsToRead, lpNumberOfCharsRead, lpReserved: INTEGER): INTEGER; +PROCEDURE [windows-, KERNEL, ""] ReadConsoleA* (hConsoleInput, lpBuffer, nNumberOfCharsToRead, lpNumberOfCharsRead, lpReserved: INTEGER): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "GetCommandLineA"] - GetCommandLine* (): INTEGER; +PROCEDURE [windows-, KERNEL, ""] GetCommandLineA* (): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "GlobalAlloc"] - GlobalAlloc* (uFlags, dwBytes: INTEGER): INTEGER; +PROCEDURE [windows-, KERNEL, ""] GlobalAlloc* (uFlags, dwBytes: INTEGER): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "GlobalFree"] - GlobalFree* (hMem: INTEGER): INTEGER; +PROCEDURE [windows-, KERNEL, ""] GlobalFree* (hMem: INTEGER): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "WriteConsoleW"] - WriteConsoleW* (hConsoleOutput, lpBuffer, nNumberOfCharsToWrite, lpNumberOfCharsWritten, lpReserved: INTEGER): INTEGER; +PROCEDURE [windows-, KERNEL, ""] WriteConsoleW* (hConsoleOutput, lpBuffer, nNumberOfCharsToWrite, lpNumberOfCharsWritten, lpReserved: INTEGER): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "ExitProcess"] - ExitProcess* (code: INTEGER); +PROCEDURE [windows-, KERNEL, ""] ExitProcess* (code: INTEGER); -PROCEDURE [windows-, "kernel32.dll", "WriteConsoleA"] - WriteConsole* (hConsoleOutput, lpBuffer, nNumberOfCharsToWrite, lpNumberOfCharsWritten, lpReserved: INTEGER): INTEGER; +PROCEDURE [windows-, KERNEL, ""] WriteConsoleA* (hConsoleOutput, lpBuffer, nNumberOfCharsToWrite, lpNumberOfCharsWritten, lpReserved: INTEGER): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "GetTickCount"] - GetTickCount* (): INTEGER; +PROCEDURE [windows-, KERNEL, ""] GetTickCount* (): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "Sleep"] - Sleep* (dwMilliseconds: INTEGER); +PROCEDURE [windows-, KERNEL, ""] Sleep* (dwMilliseconds: INTEGER); -PROCEDURE [windows-, "kernel32.dll", "FreeLibrary"] - FreeLibrary* (hLibModule: INTEGER): INTEGER; +PROCEDURE [windows-, KERNEL, ""] FreeLibrary* (hLibModule: INTEGER): INTEGER; -PROCEDURE [ccall, "msvcrt.dll", "rand"] - rand* (): INTEGER; +PROCEDURE [windows-, KERNEL, ""] GetProcAddress* (hModule, name: INTEGER): INTEGER; -PROCEDURE [ccall, "msvcrt.dll", "srand"] - srand* (seed: INTEGER); +PROCEDURE [windows-, KERNEL, ""] LoadLibraryA* (name: INTEGER): INTEGER; -PROCEDURE [windows-, "user32.dll", "MessageBoxA"] - MessageBoxA* (hWnd, lpText, lpCaption, uType: INTEGER): INTEGER; +PROCEDURE [windows-, KERNEL, ""] AllocConsole* (): BOOLEAN; -PROCEDURE [windows-, "user32.dll", "MessageBoxW"] - MessageBox* (hWnd, lpText, lpCaption, uType: INTEGER): INTEGER; +PROCEDURE [windows-, KERNEL, ""] FreeConsole* (): BOOLEAN; -PROCEDURE [windows-, "user32.dll", "CreateWindowExA"] - CreateWindowEx* ( +PROCEDURE [windows-, USER, ""] MessageBoxA* (hWnd, lpText, lpCaption, uType: INTEGER): INTEGER; + +PROCEDURE [windows-, USER, ""] MessageBoxW* (hWnd, lpText, lpCaption, uType: INTEGER): INTEGER; + +PROCEDURE [windows-, USER, ""] CreateWindowExA* ( dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam: INTEGER): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "GetProcAddress"] - GetProcAddress* (hModule, name: INTEGER): INTEGER; +PROCEDURE [ccall-, MSVCRT, ""] time* (ptr: INTEGER): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "LoadLibraryA"] - LoadLibraryA* (name: INTEGER): INTEGER; - -PROCEDURE [windows-, "kernel32.dll", "AllocConsole"] - AllocConsole* (): BOOLEAN; - -PROCEDURE [windows-, "kernel32.dll", "FreeConsole"] - FreeConsole* (): BOOLEAN; +PROCEDURE [ccall-, MSVCRT, ""] mktime* (time: tm): INTEGER; PROCEDURE SetDllEntry* (process_detach, thread_detach, thread_attach: DLL_ENTRY); @@ -238,4 +221,4 @@ BEGIN END SetDllEntry; -END WINAPI. +END WINAPI. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows64/API.ob07 b/programs/develop/oberon07/Lib/Windows64/API.ob07 index 0eaf6c9a7..437d08b89 100644 --- a/programs/develop/oberon07/Lib/Windows64/API.ob07 +++ b/programs/develop/oberon07/Lib/Windows64/API.ob07 @@ -12,6 +12,8 @@ IMPORT SYSTEM; CONST + eol* = 0DX + 0AX; + SectionAlignment = 1000H; DLL_PROCESS_ATTACH = 1; @@ -19,6 +21,9 @@ CONST DLL_THREAD_DETACH = 3; DLL_PROCESS_DETACH = 0; + KERNEL = "kernel32.dll"; + USER = "user32.dll"; + TYPE @@ -27,7 +32,6 @@ TYPE VAR - eol*: ARRAY 3 OF CHAR; base*: INTEGER; heap: INTEGER; @@ -36,13 +40,12 @@ VAR thread_attach: DLL_ENTRY; -PROCEDURE [windows-, "kernel32.dll", "ExitProcess"] ExitProcess (code: INTEGER); -PROCEDURE [windows-, "kernel32.dll", "ExitThread"] ExitThread (code: INTEGER); -PROCEDURE [windows-, "kernel32.dll", "GetProcessHeap"] GetProcessHeap (): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "HeapAlloc"] HeapAlloc (hHeap, dwFlags, dwBytes: INTEGER): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "HeapFree"] HeapFree(hHeap, dwFlags, lpMem: INTEGER); - -PROCEDURE [windows-, "user32.dll", "MessageBoxA"] MessageBoxA (hWnd, lpText, lpCaption, uType: INTEGER): INTEGER; +PROCEDURE [windows-, KERNEL, ""] ExitProcess (code: INTEGER); +PROCEDURE [windows-, KERNEL, ""] ExitThread (code: INTEGER); +PROCEDURE [windows-, KERNEL, ""] GetProcessHeap (): INTEGER; +PROCEDURE [windows-, KERNEL, ""] HeapAlloc (hHeap, dwFlags, dwBytes: INTEGER): INTEGER; +PROCEDURE [windows-, KERNEL, ""] HeapFree (hHeap, dwFlags, lpMem: INTEGER); +PROCEDURE [windows-, USER, ""] MessageBoxA (hWnd, lpText, lpCaption, uType: INTEGER): INTEGER; PROCEDURE DebugMsg* (lpText, lpCaption: INTEGER); @@ -68,7 +71,6 @@ BEGIN process_detach := NIL; thread_detach := NIL; thread_attach := NIL; - eol[0] := 0DX; eol[1] := 0AX; eol[2] := 0X; base := code - SectionAlignment; heap := GetProcessHeap() END init; diff --git a/programs/develop/oberon07/Lib/Windows64/Args.ob07 b/programs/develop/oberon07/Lib/Windows64/Args.ob07 new file mode 100644 index 000000000..3d4ae39cf --- /dev/null +++ b/programs/develop/oberon07/Lib/Windows64/Args.ob07 @@ -0,0 +1,101 @@ +(* + BSD 2-Clause License + + Copyright (c) 2019-2020, Anton Krotov + All rights reserved. +*) + +MODULE Args; + +IMPORT SYSTEM, WINAPI; + + +CONST + + MAX_PARAM = 1024; + + +VAR + + Params: ARRAY MAX_PARAM, 2 OF INTEGER; + argc*: INTEGER; + + +PROCEDURE GetChar (adr: INTEGER): CHAR; +VAR + res: CHAR; + +BEGIN + SYSTEM.GET(adr, res) + RETURN res +END GetChar; + + +PROCEDURE ParamParse; +VAR + p, count, cond: INTEGER; + c: CHAR; + + + PROCEDURE ChangeCond (A, B, C: INTEGER; VAR cond: INTEGER; c: CHAR): INTEGER; + BEGIN + IF (c <= 20X) & (c # 0X) THEN + cond := A + ELSIF c = 22X THEN + cond := B + ELSIF c = 0X THEN + cond := 6 + ELSE + cond := C + END + + RETURN cond + END ChangeCond; + + +BEGIN + p := WINAPI.GetCommandLineA(); + cond := 0; + count := 0; + WHILE (count < MAX_PARAM) & (cond # 6) DO + c := GetChar(p); + CASE cond OF + |0: IF ChangeCond(0, 4, 1, cond, c) = 1 THEN Params[count, 0] := p END + |1: IF ChangeCond(0, 3, 1, cond, c) IN {0, 6} THEN Params[count, 1] := p - 1; INC(count) END + |3: IF ChangeCond(3, 1, 3, cond, c) = 6 THEN Params[count, 1] := p - 1; INC(count) END + |4: IF ChangeCond(5, 0, 5, cond, c) = 5 THEN Params[count, 0] := p END + |5: IF ChangeCond(5, 1, 5, cond, c) = 6 THEN Params[count, 1] := p - 1; INC(count) END + |6: + END; + INC(p) + END; + argc := count +END ParamParse; + + +PROCEDURE GetArg* (n: INTEGER; VAR s: ARRAY OF CHAR); +VAR + i, j, len: INTEGER; + c: CHAR; + +BEGIN + j := 0; + IF n < argc THEN + i := Params[n, 0]; + len := LEN(s) - 1; + WHILE (j < len) & (i <= Params[n, 1]) DO + c := GetChar(i); + IF c # '"' THEN + s[j] := c; + INC(j) + END; + INC(i) + END + END; + s[j] := 0X +END GetArg; + + +BEGIN + ParamParse +END Args. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows64/Console.ob07 b/programs/develop/oberon07/Lib/Windows64/Console.ob07 index 042b0317a..d11e06db4 100644 --- a/programs/develop/oberon07/Lib/Windows64/Console.ob07 +++ b/programs/develop/oberon07/Lib/Windows64/Console.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2019, Anton Krotov + Copyright (c) 2019-2020, Anton Krotov All rights reserved. *) @@ -48,7 +48,7 @@ VAR BEGIN WINAPI.GetConsoleScreenBufferInfo(hConsoleOutput, ScrBufInfo); fill := ORD(ScrBufInfo.dwSize.X) * ORD(ScrBufInfo.dwSize.Y); - WINAPI.FillConsoleOutputCharacter(hConsoleOutput, 20H, fill, 0, SYSTEM.ADR(fill)); + WINAPI.FillConsoleOutputCharacterA(hConsoleOutput, 20H, fill, 0, SYSTEM.ADR(fill)); WINAPI.FillConsoleOutputAttribute(hConsoleOutput, ORD(ScrBufInfo.wAttributes), fill, 0, SYSTEM.ADR(fill)); SetCursor(0, 0) END Cls; diff --git a/programs/develop/oberon07/Lib/Windows64/DateTime.ob07 b/programs/develop/oberon07/Lib/Windows64/DateTime.ob07 index bd849fb70..f527c18f2 100644 --- a/programs/develop/oberon07/Lib/Windows64/DateTime.ob07 +++ b/programs/develop/oberon07/Lib/Windows64/DateTime.ob07 @@ -1,13 +1,13 @@ (* BSD 2-Clause License - Copyright (c) 2019, Anton Krotov + Copyright (c) 2019-2020, Anton Krotov All rights reserved. *) MODULE DateTime; -IMPORT WINAPI; +IMPORT WINAPI, SYSTEM; CONST @@ -116,6 +116,29 @@ BEGIN END NowEncode; +PROCEDURE NowUnixTime* (): INTEGER; + RETURN WINAPI.time(0) +END NowUnixTime; + + +PROCEDURE UnixTime* (Year, Month, Day, Hour, Min, Sec: INTEGER): INTEGER; +VAR + t: WINAPI.tm; + +BEGIN + DEC(Year, 1900); + DEC(Month); + SYSTEM.GET(SYSTEM.ADR(Sec), t.sec); + SYSTEM.GET(SYSTEM.ADR(Min), t.min); + SYSTEM.GET(SYSTEM.ADR(Hour), t.hour); + SYSTEM.GET(SYSTEM.ADR(Day), t.mday); + SYSTEM.GET(SYSTEM.ADR(Month), t.mon); + SYSTEM.GET(SYSTEM.ADR(Year), t.year); + + RETURN WINAPI.mktime(t) +END UnixTime; + + PROCEDURE init; VAR day, year, month, i: INTEGER; diff --git a/programs/develop/oberon07/Lib/Windows64/File.ob07 b/programs/develop/oberon07/Lib/Windows64/File.ob07 new file mode 100644 index 000000000..4e003eee3 --- /dev/null +++ b/programs/develop/oberon07/Lib/Windows64/File.ob07 @@ -0,0 +1,139 @@ +(* + BSD 2-Clause License + + Copyright (c) 2019-2020, Anton Krotov + All rights reserved. +*) + +MODULE File; + +IMPORT SYSTEM, WINAPI, API; + + +CONST + + OPEN_R* = 0; OPEN_W* = 1; OPEN_RW* = 2; + SEEK_BEG* = 0; SEEK_CUR* = 1; SEEK_END* = 2; + + +PROCEDURE Exists* (FName: ARRAY OF CHAR): BOOLEAN; +VAR + FindData: WINAPI.TWin32FindData; + Handle: INTEGER; + attr: SET; + +BEGIN + Handle := WINAPI.FindFirstFileA(SYSTEM.ADR(FName[0]), FindData); + IF Handle # -1 THEN + WINAPI.FindClose(Handle); + SYSTEM.GET32(SYSTEM.ADR(FindData.dwFileAttributes), attr); + IF 4 IN attr THEN + Handle := -1 + END + END + + RETURN Handle # -1 +END Exists; + + +PROCEDURE Delete* (FName: ARRAY OF CHAR): BOOLEAN; + RETURN WINAPI.DeleteFileA(SYSTEM.ADR(FName[0])) # 0 +END Delete; + + +PROCEDURE Create* (FName: ARRAY OF CHAR): INTEGER; + RETURN WINAPI.CreateFileA(SYSTEM.ADR(FName[0]), 0C0000000H, 0, NIL, 2, 80H, 0) +END Create; + + +PROCEDURE Close* (F: INTEGER); +BEGIN + WINAPI.CloseHandle(F) +END Close; + + +PROCEDURE Open* (FName: ARRAY OF CHAR; Mode: INTEGER): INTEGER; +VAR + ofstr: WINAPI.OFSTRUCT; +BEGIN + RETURN WINAPI.OpenFile(SYSTEM.ADR(FName[0]), ofstr, Mode) +END Open; + + +PROCEDURE Seek* (F, Offset, Origin: INTEGER): INTEGER; + RETURN WINAPI.SetFilePointer(F, Offset MOD 100000000H, SYSTEM.ADR(Offset) + 4, Origin) +END Seek; + + +PROCEDURE Read* (F, Buffer, Count: INTEGER): INTEGER; +VAR + res: INTEGER; + +BEGIN + IF WINAPI.ReadFile(F, Buffer, Count, SYSTEM.ADR(res), NIL) = 0 THEN + res := -1 + END + + RETURN res +END Read; + + +PROCEDURE Write* (F, Buffer, Count: INTEGER): INTEGER; +VAR + res: INTEGER; + +BEGIN + IF WINAPI.WriteFile(F, Buffer, Count, SYSTEM.ADR(res), NIL) = 0 THEN + res := -1 + END + + RETURN res +END Write; + + +PROCEDURE Load* (FName: ARRAY OF CHAR; VAR Size: INTEGER): INTEGER; +VAR + res, n, F: INTEGER; + +BEGIN + res := 0; + F := Open(FName, OPEN_R); + + IF F # -1 THEN + Size := Seek(F, 0, SEEK_END); + n := Seek(F, 0, SEEK_BEG); + res := API._NEW(Size); + IF (res = 0) OR (Read(F, res, Size) # Size) THEN + IF res # 0 THEN + res := API._DISPOSE(res); + Size := 0 + END + END; + Close(F) + END + + RETURN res +END Load; + + +PROCEDURE RemoveDir* (DirName: ARRAY OF CHAR): BOOLEAN; + RETURN WINAPI.RemoveDirectoryA(SYSTEM.ADR(DirName[0])) # 0 +END RemoveDir; + + +PROCEDURE ExistsDir* (DirName: ARRAY OF CHAR): BOOLEAN; +VAR + Code: SET; + +BEGIN + Code := WINAPI.GetFileAttributesA(SYSTEM.ADR(DirName[0])) + RETURN (Code # {0..31}) & (4 IN Code) +END ExistsDir; + + +PROCEDURE CreateDir* (DirName: ARRAY OF CHAR): BOOLEAN; + RETURN WINAPI.CreateDirectoryA(SYSTEM.ADR(DirName[0]), NIL) # 0 +END CreateDir; + + +END File. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows64/HOST.ob07 b/programs/develop/oberon07/Lib/Windows64/HOST.ob07 index ee6b7bf77..20301868c 100644 --- a/programs/develop/oberon07/Lib/Windows64/HOST.ob07 +++ b/programs/develop/oberon07/Lib/Windows64/HOST.ob07 @@ -13,7 +13,7 @@ IMPORT SYSTEM, RTL; CONST slash* = "\"; - OS* = "WINDOWS"; + eol* = 0DX + 0AX; bit_depth* = RTL.bit_depth; maxint* = RTL.maxint; @@ -59,19 +59,6 @@ TYPE END; - TSystemTime = RECORD - - Year, - Month, - DayOfWeek, - Day, - Hour, - Min, - Sec, - MSec: WCHAR - - END; - VAR @@ -80,8 +67,6 @@ VAR Params: ARRAY MAX_PARAM, 2 OF INTEGER; argc: INTEGER; - eol*: ARRAY 3 OF CHAR; - maxreal*: REAL; @@ -116,12 +101,12 @@ PROCEDURE [windows-, "kernel32.dll", "OpenFile"] PROCEDURE [windows-, "kernel32.dll", "GetCurrentDirectoryA"] _GetCurrentDirectory (nBufferLength, lpBuffer: INTEGER): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "GetSystemTime"] - _GetSystemTime (T: TSystemTime); - -PROCEDURE [windows-, "kernel32.dll", "ExitProcess"] +PROCEDURE [windows, "kernel32.dll", "ExitProcess"] _ExitProcess (code: INTEGER); +PROCEDURE [windows, "msvcrt.dll", "time"] + _time (ptr: INTEGER): INTEGER; + PROCEDURE ExitProcess* (code: INTEGER); BEGIN @@ -215,13 +200,11 @@ END GetArg; PROCEDURE FileRead* (F: INTEGER; VAR Buffer: ARRAY OF CHAR; bytes: INTEGER): INTEGER; VAR - res, n: INTEGER; + res: INTEGER; BEGIN - IF _ReadFile(F, SYSTEM.ADR(Buffer[0]), bytes, n, NIL) = 0 THEN + IF _ReadFile(F, SYSTEM.ADR(Buffer[0]), bytes, res, NIL) = 0 THEN res := -1 - ELSE - res := n END RETURN res @@ -230,13 +213,11 @@ END FileRead; PROCEDURE FileWrite* (F: INTEGER; Buffer: ARRAY OF BYTE; bytes: INTEGER): INTEGER; VAR - res, n: INTEGER; + res: INTEGER; BEGIN - IF _WriteFile(F, SYSTEM.ADR(Buffer[0]), bytes, n, NIL) = 0 THEN + IF _WriteFile(F, SYSTEM.ADR(Buffer[0]), bytes, res, NIL) = 0 THEN res := -1 - ELSE - res := n END RETURN res @@ -269,6 +250,10 @@ BEGIN END FileOpen; +PROCEDURE chmod* (FName: ARRAY OF CHAR); +END chmod; + + PROCEDURE OutChar* (c: CHAR); VAR count: INTEGER; @@ -292,24 +277,23 @@ PROCEDURE isRelative* (path: ARRAY OF CHAR): BOOLEAN; END isRelative; -PROCEDURE now* (VAR year, month, day, hour, min, sec: INTEGER); +PROCEDURE UnixTime* (): INTEGER; + RETURN _time(0) +END UnixTime; + + +PROCEDURE splitf* (x: REAL; VAR a, b: INTEGER): INTEGER; VAR - T: TSystemTime; + res: INTEGER; BEGIN - _GetSystemTime(T); - year := ORD(T.Year); - month := ORD(T.Month); - day := ORD(T.Day); - hour := ORD(T.Hour); - min := ORD(T.Min); - sec := ORD(T.Sec) -END now; - - -PROCEDURE UnixTime* (): INTEGER; - RETURN 0 -END UnixTime; + a := 0; + b := 0; + SYSTEM.GET32(SYSTEM.ADR(x), a); + SYSTEM.GET32(SYSTEM.ADR(x) + 4, b); + SYSTEM.GET(SYSTEM.ADR(x), res) + RETURN res +END splitf; PROCEDURE d2s* (x: REAL): INTEGER; @@ -317,8 +301,7 @@ VAR h, l, s, e: INTEGER; BEGIN - SYSTEM.GET(SYSTEM.ADR(x), l); - SYSTEM.GET(SYSTEM.ADR(x) + 4, h); + e := splitf(x, l, h); s := ASR(h, 31) MOD 2; e := (h DIV 100000H) MOD 2048; @@ -348,22 +331,7 @@ BEGIN END d2s; -PROCEDURE splitf* (x: REAL; VAR a, b: INTEGER): INTEGER; -VAR - res: INTEGER; - BEGIN - a := 0; - b := 0; - SYSTEM.MOVE(SYSTEM.ADR(x), SYSTEM.ADR(a), 4); - SYSTEM.MOVE(SYSTEM.ADR(x) + 4, SYSTEM.ADR(b), 4); - SYSTEM.GET(SYSTEM.ADR(x), res) - RETURN res -END splitf; - - -BEGIN - eol[0] := 0DX; eol[1] := 0AX; eol[2] := 0X; maxreal := 1.9; PACK(maxreal, 1023); hConsoleOutput := _GetStdHandle(-11); diff --git a/programs/develop/oberon07/Lib/Windows64/In.ob07 b/programs/develop/oberon07/Lib/Windows64/In.ob07 index dd4b51860..1e2b21f57 100644 --- a/programs/develop/oberon07/Lib/Windows64/In.ob07 +++ b/programs/develop/oberon07/Lib/Windows64/In.ob07 @@ -1,290 +1,74 @@ (* - Copyright 2013, 2017, 2018, 2019 Anton Krotov + BSD 2-Clause License - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . + Copyright (c) 2020, Anton Krotov + All rights reserved. *) MODULE In; -IMPORT sys := SYSTEM; +IMPORT SYSTEM; -TYPE - STRING = ARRAY 260 OF CHAR; +CONST + + MAX_LEN = 1024; + VAR - Done*: BOOLEAN; - hConsoleInput: INTEGER; + Done*: BOOLEAN; + hConsoleInput: INTEGER; + s: ARRAY MAX_LEN + 4 OF CHAR; -PROCEDURE [windows-, "kernel32.dll", "GetStdHandle"] - GetStdHandle (nStdHandle: INTEGER): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "ReadConsoleA"] - ReadConsole (hConsoleInput, lpBuffer, nNumberOfCharsToRead, lpNumberOfCharsRead, lpReserved: INTEGER): INTEGER; +PROCEDURE [windows, "msvcrt.dll", ""] sscanf (buf: INTEGER; fmt: INTEGER; adr: INTEGER): INTEGER; +PROCEDURE [windows, "kernel32.dll", ""] GetStdHandle (nStdHandle: INTEGER): INTEGER; +PROCEDURE [windows, "kernel32.dll", ""] ReadConsoleA (hConsoleInput, lpBuffer, nNumberOfCharsToRead, lpNumberOfCharsRead, lpReserved: INTEGER); -PROCEDURE digit(ch: CHAR): BOOLEAN; - RETURN (ch >= "0") & (ch <= "9") -END digit; -PROCEDURE CheckInt(s: STRING; VAR first, last: INTEGER; VAR neg: BOOLEAN; Point: BOOLEAN): BOOLEAN; -VAR i: INTEGER; +PROCEDURE String* (VAR str: ARRAY OF CHAR); +VAR + count: INTEGER; + BEGIN - i := 0; - neg := FALSE; - WHILE (s[i] <= 20X) & (s[i] # 0X) DO - INC(i) - END; - IF s[i] = "-" THEN - neg := TRUE; - INC(i) - ELSIF s[i] = "+" THEN - INC(i) - END; - first := i; - WHILE digit(s[i]) DO - INC(i) - END; - last := i - RETURN ((s[i] <= 20X) OR (Point & (s[i] = "."))) & digit(s[first]) -END CheckInt; - -PROCEDURE IsMinInt(str: STRING; pos: INTEGER): BOOLEAN; -VAR i: INTEGER; min: STRING; -BEGIN - i := 0; - min := "2147483648"; - WHILE (min[i] # 0X) & (str[i] # 0X) & (min[i] = str[i + pos]) DO - INC(i) - END - RETURN i = 10 -END IsMinInt; - -PROCEDURE StrToInt(str: STRING; VAR err: BOOLEAN): INTEGER; -CONST maxINT = 7FFFFFFFH; -VAR i, n, res: INTEGER; flag, neg: BOOLEAN; -BEGIN - res := 0; - flag := CheckInt(str, i, n, neg, FALSE); - err := ~flag; - IF flag & neg & IsMinInt(str, i) THEN - flag := FALSE; - neg := FALSE; - res := 80000000H - END; - WHILE flag & digit(str[i]) DO - IF res > maxINT DIV 10 THEN - err := TRUE; - flag := FALSE; - res := 0 - ELSE - res := res * 10; - IF res > maxINT - (ORD(str[i]) - ORD("0")) THEN - err := TRUE; - flag := FALSE; - res := 0 - ELSE - res := res + (ORD(str[i]) - ORD("0")); - INC(i) - END - END - END; - IF neg THEN - res := -res - END - RETURN res -END StrToInt; - -PROCEDURE Space(s: STRING): BOOLEAN; -VAR i: INTEGER; -BEGIN - i := 0; - WHILE (s[i] # 0X) & (s[i] <= 20X) DO - INC(i) - END - RETURN s[i] = 0X -END Space; - -PROCEDURE CheckReal(s: STRING; VAR n: INTEGER; VAR neg: BOOLEAN): BOOLEAN; -VAR i: INTEGER; Res: BOOLEAN; -BEGIN - Res := CheckInt(s, n, i, neg, TRUE); - IF Res THEN - IF s[i] = "." THEN - INC(i); - WHILE digit(s[i]) DO - INC(i) - END; - IF (s[i] = "D") OR (s[i] = "E") OR (s[i] = "d") OR (s[i] = "e") THEN - INC(i); - IF (s[i] = "+") OR (s[i] = "-") THEN - INC(i) - END; - Res := digit(s[i]); - WHILE digit(s[i]) DO - INC(i) - END - END - END - END - RETURN Res & (s[i] <= 20X) -END CheckReal; - -PROCEDURE StrToFloat(str: STRING; VAR err: BOOLEAN): REAL; -CONST maxDBL = 1.69E308; maxINT = 7FFFFFFFH; -VAR i, scale: INTEGER; res, m, d: REAL; minus, neg: BOOLEAN; - - PROCEDURE part1(VAR res, d: REAL; VAR i: INTEGER; str: STRING): BOOLEAN; - BEGIN - res := 0.0; - d := 1.0; - WHILE digit(str[i]) DO - res := res * 10.0 + FLT(ORD(str[i]) - ORD("0")); - INC(i) + ReadConsoleA(hConsoleInput, SYSTEM.ADR(s[0]), MAX_LEN, SYSTEM.ADR(count), 0); + IF (s[count - 1] = 0AX) & (s[count - 2] = 0DX) THEN + DEC(count, 2) END; - IF str[i] = "." THEN - INC(i); - WHILE digit(str[i]) DO - d := d / 10.0; - res := res + FLT(ORD(str[i]) - ORD("0")) * d; - INC(i) - END - END - RETURN str[i] # 0X - END part1; - - PROCEDURE part2(VAR i, scale: INTEGER; VAR m, res: REAL; VAR minus, err: BOOLEAN; str: STRING): BOOLEAN; - BEGIN - INC(i); - m := 10.0; - minus := FALSE; - IF str[i] = "+" THEN - INC(i) - ELSIF str[i] = "-" THEN - minus := TRUE; - INC(i); - m := 0.1 - END; - scale := 0; - err := FALSE; - WHILE ~err & digit(str[i]) DO - IF scale > maxINT DIV 10 THEN - err := TRUE; - res := 0.0 - ELSE - scale := scale * 10; - IF scale > maxINT - (ORD(str[i]) - ORD("0")) THEN - err := TRUE; - res := 0.0 - ELSE - scale := scale + (ORD(str[i]) - ORD("0")); - INC(i) - END - END - END - RETURN ~err - END part2; - - PROCEDURE part3 (VAR err, minus: BOOLEAN; VAR scale: INTEGER; VAR res, m: REAL); - VAR i: INTEGER; - BEGIN - err := FALSE; - IF scale = maxINT THEN - err := TRUE; - res := 0.0 - END; - i := 1; - WHILE ~err & (i <= scale) DO - IF ~minus & (res > maxDBL / m) THEN - err := TRUE; - res := 0.0 - ELSE - res := res * m; - INC(i) - END - END - END part3; - -BEGIN - IF CheckReal(str, i, neg) THEN - IF part1(res, d, i, str) & part2(i, scale, m, res, minus, err, str) THEN - part3(err, minus, scale, res, m) - END; - IF neg THEN - res := -res - END - ELSE - res := 0.0; - err := TRUE - END - RETURN res -END StrToFloat; - -PROCEDURE String*(VAR s: ARRAY OF CHAR); -VAR count, i: INTEGER; str: STRING; -BEGIN - ReadConsole(hConsoleInput, sys.ADR(str[0]), 256, sys.ADR(count), 0); - IF (str[count - 1] = 0AX) & (str[count - 2] = 0DX) THEN - DEC(count, 2) - END; - str[256] := 0X; - str[count] := 0X; - i := 0; - WHILE (i < LEN(s) - 1) & (i < LEN(str)) & (str[i] # 0X) DO - s[i] := str[i]; - INC(i) - END; - s[i] := 0X; - Done := TRUE + s[count] := 0X; + COPY(s, str); + str[LEN(str) - 1] := 0X; + Done := TRUE END String; -PROCEDURE Char*(VAR x: CHAR); -VAR str: STRING; -BEGIN - String(str); - x := str[0]; - Done := TRUE -END Char; -PROCEDURE Ln*; -VAR str: STRING; +PROCEDURE Int* (VAR x: INTEGER); BEGIN - String(str); - Done := TRUE -END Ln; + String(s); + Done := sscanf(SYSTEM.ADR(s[0]), SYSTEM.SADR("%lld"), SYSTEM.ADR(x)) = 1 +END Int; -PROCEDURE Real*(VAR x: REAL); -VAR str: STRING; err: BOOLEAN; + +PROCEDURE Real* (VAR x: REAL); BEGIN - err := FALSE; - REPEAT - String(str) - UNTIL ~Space(str); - x := StrToFloat(str, err); - Done := ~err + String(s); + Done := sscanf(SYSTEM.ADR(s[0]), SYSTEM.SADR("%lf"), SYSTEM.ADR(x)) = 1 END Real; -PROCEDURE Int*(VAR x: INTEGER); -VAR str: STRING; err: BOOLEAN; + +PROCEDURE Char* (VAR x: CHAR); BEGIN - err := FALSE; - REPEAT - String(str) - UNTIL ~Space(str); - x := StrToInt(str, err); - Done := ~err -END Int; + String(s); + x := s[0] +END Char; + + +PROCEDURE Ln*; +BEGIN + String(s) +END Ln; + PROCEDURE Open*; BEGIN @@ -292,4 +76,5 @@ BEGIN Done := TRUE END Open; + END In. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows64/Math.ob07 b/programs/develop/oberon07/Lib/Windows64/Math.ob07 index ab80d79eb..42a5de5e7 100644 --- a/programs/develop/oberon07/Lib/Windows64/Math.ob07 +++ b/programs/develop/oberon07/Lib/Windows64/Math.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2019, Anton Krotov + Copyright (c) 2019-2020, Anton Krotov All rights reserved. *) @@ -12,22 +12,32 @@ IMPORT SYSTEM; CONST - e *= 2.71828182845904523; - pi *= 3.14159265358979324; - ln2 *= 0.693147180559945309; + pi* = 3.1415926535897932384626433832795028841972E0; + e* = 2.7182818284590452353602874713526624977572E0; - eps = 1.0E-16; - MaxCosArg = 1000000.0 * pi; + ZERO = 0.0E0; + ONE = 1.0E0; + HALF = 0.5E0; + TWO = 2.0E0; + sqrtHalf = 0.70710678118654752440E0; + eps = 5.5511151E-17; + ln2Inv = 1.44269504088896340735992468100189213E0; + piInv = ONE / pi; + Limit = 1.0536712E-8; + piByTwo = pi / TWO; + + expoMax = 1023; + expoMin = 1 - expoMax; VAR - Exp: ARRAY 710 OF REAL; + LnInfinity, LnSmall, large, miny: REAL; PROCEDURE [stdcall64] sqrt* (x: REAL): REAL; BEGIN - ASSERT(x >= 0.0); + ASSERT(x >= ZERO); SYSTEM.CODE( 0F2H, 0FH, 51H, 45H, 10H, (* sqrtsd xmm0, qword[rbp + 10h] *) 05DH, (* pop rbp *) @@ -38,205 +48,340 @@ BEGIN END sqrt; +PROCEDURE sqri* (x: INTEGER): INTEGER; + RETURN x * x +END sqri; + + +PROCEDURE sqrr* (x: REAL): REAL; + RETURN x * x +END sqrr; + + PROCEDURE exp* (x: REAL): REAL; CONST - e25 = 1.284025416687741484; (* exp(0.25) *) + c1 = 0.693359375E0; + c2 = -2.1219444005469058277E-4; + P0 = 0.249999999999999993E+0; + P1 = 0.694360001511792852E-2; + P2 = 0.165203300268279130E-4; + Q1 = 0.555538666969001188E-1; + Q2 = 0.495862884905441294E-3; VAR - a, s, res: REAL; - neg: BOOLEAN; + xn, g, p, q, z: REAL; n: INTEGER; BEGIN - neg := x < 0.0; - IF neg THEN - x := -x - END; - - IF x < FLT(LEN(Exp)) THEN - res := Exp[FLOOR(x)]; - x := x - FLT(FLOOR(x)); - WHILE x >= 0.25 DO - res := res * e25; - x := x - 0.25 - END + IF x > LnInfinity THEN + x := SYSTEM.INF() + ELSIF x < LnSmall THEN + x := ZERO + ELSIF ABS(x) < eps THEN + x := ONE ELSE - res := SYSTEM.INF(); - x := 0.0 - END; + IF x >= ZERO THEN + n := FLOOR(ln2Inv * x + HALF) + ELSE + n := FLOOR(ln2Inv * x - HALF) + END; - n := 0; - a := 1.0; - s := 1.0; - - REPEAT - INC(n); - a := a * x / FLT(n); - s := s + a - UNTIL a < eps; - - IF neg THEN - res := 1.0 / (res * s) - ELSE - res := res * s + xn := FLT(n); + g := (x - xn * c1) - xn * c2; + z := g * g; + p := ((P2 * z + P1) * z + P0) * g; + q := (Q2 * z + Q1) * z + HALF; + x := HALF + p / (q - p); + PACK(x, n + 1) END - RETURN res + RETURN x END exp; PROCEDURE ln* (x: REAL): REAL; +CONST + c1 = 355.0E0 / 512.0E0; + c2 = -2.121944400546905827679E-4; + P0 = -0.64124943423745581147E+2; + P1 = 0.16383943563021534222E+2; + P2 = -0.78956112887491257267E+0; + Q0 = -0.76949932108494879777E+3; + Q1 = 0.31203222091924532844E+3; + Q2 = -0.35667977739034646171E+2; + VAR - a, x2, res: REAL; + zn, zd, r, z, w, p, q, xn: REAL; n: INTEGER; BEGIN - ASSERT(x > 0.0); + ASSERT(x > ZERO); + UNPK(x, n); + x := x * HALF; - x := (x - 1.0) / (x + 1.0); - x2 := x * x; - res := x + FLT(n) * (ln2 * 0.5); - n := 1; + IF x > sqrtHalf THEN + zn := x - ONE; + zd := x * HALF + HALF; + INC(n) + ELSE + zn := x - HALF; + zd := zn * HALF + HALF + END; - REPEAT - INC(n, 2); - x := x * x2; - a := x / FLT(n); - res := res + a - UNTIL a < eps + z := zn / zd; + w := z * z; + q := ((w + Q2) * w + Q1) * w + Q0; + p := w * ((P2 * w + P1) * w + P0); + r := z + z * (p / q); + xn := FLT(n) - RETURN res * 2.0 + RETURN (xn * c2 + r) + xn * c1 END ln; PROCEDURE power* (base, exponent: REAL): REAL; BEGIN - ASSERT(base > 0.0) + ASSERT(base > ZERO) RETURN exp(exponent * ln(base)) END power; +PROCEDURE ipower* (base: REAL; exponent: INTEGER): REAL; +VAR + i: INTEGER; + a: REAL; + +BEGIN + a := 1.0; + + IF base # 0.0 THEN + IF exponent # 0 THEN + IF exponent < 0 THEN + base := 1.0 / base + END; + i := ABS(exponent); + WHILE i > 0 DO + WHILE ~ODD(i) DO + i := LSR(i, 1); + base := sqrr(base) + END; + DEC(i); + a := a * base + END + ELSE + a := 1.0 + END + ELSE + ASSERT(exponent > 0); + a := 0.0 + END + + RETURN a +END ipower; + + PROCEDURE log* (base, x: REAL): REAL; BEGIN - ASSERT(base > 0.0); - ASSERT(x > 0.0) + ASSERT(base > ZERO); + ASSERT(x > ZERO) RETURN ln(x) / ln(base) END log; -PROCEDURE cos* (x: REAL): REAL; +PROCEDURE SinCos (x, y, sign: REAL): REAL; +CONST + ymax = 210828714; + c1 = 3.1416015625E0; + c2 = -8.908910206761537356617E-6; + r1 = -0.16666666666666665052E+0; + r2 = 0.83333333333331650314E-2; + r3 = -0.19841269841201840457E-3; + r4 = 0.27557319210152756119E-5; + r5 = -0.25052106798274584544E-7; + r6 = 0.16058936490371589114E-9; + r7 = -0.76429178068910467734E-12; + r8 = 0.27204790957888846175E-14; + VAR - a, res: REAL; n: INTEGER; + xn, f, x1, g: REAL; BEGIN + ASSERT(y < FLT(ymax)); + + n := FLOOR(y * piInv + HALF); + xn := FLT(n); + IF ODD(n) THEN + sign := -sign + END; x := ABS(x); - ASSERT(x <= MaxCosArg); + IF x # y THEN + xn := xn - HALF + END; - x := x - FLT( FLOOR(x / (2.0 * pi)) ) * (2.0 * pi); - x := x * x; - res := 0.0; - a := 1.0; - n := -1; + x1 := FLT(FLOOR(x)); + f := ((x1 - xn * c1) + (x - x1)) - xn * c2; - REPEAT - INC(n, 2); - res := res + a; - a := -a * x / FLT(n*n + n) - UNTIL ABS(a) < eps + IF ABS(f) < Limit THEN + x := sign * f + ELSE + g := f * f; + g := (((((((r8 * g + r7) * g + r6) * g + r5) * g + r4) * g + r3) * g + r2) * g + r1) * g; + g := f + f * g; + x := sign * g + END - RETURN res -END cos; + RETURN x +END SinCos; PROCEDURE sin* (x: REAL): REAL; BEGIN - ASSERT(ABS(x) <= MaxCosArg); - x := cos(x) - RETURN sqrt(1.0 - x * x) -END sin; - - -PROCEDURE tan* (x: REAL): REAL; -BEGIN - ASSERT(ABS(x) <= MaxCosArg); - x := cos(x) - RETURN sqrt(1.0 - x * x) / x -END tan; - - -PROCEDURE arcsin* (x: REAL): REAL; - - - PROCEDURE arctan (x: REAL): REAL; - VAR - z, p, k: REAL; - - BEGIN - p := x / (x * x + 1.0); - z := p * x; - x := 0.0; - k := 0.0; - - REPEAT - k := k + 2.0; - x := x + p; - p := p * k * z / (k + 1.0) - UNTIL p < eps - - RETURN x - END arctan; - - -BEGIN - ASSERT(ABS(x) <= 1.0); - - IF ABS(x) >= 0.707 THEN - x := 0.5 * pi - arctan(sqrt(1.0 - x * x) / x) + IF x < ZERO THEN + x := SinCos(x, -x, -ONE) ELSE - x := arctan(x / sqrt(1.0 - x * x)) + x := SinCos(x, x, ONE) END RETURN x +END sin; + + +PROCEDURE cos* (x: REAL): REAL; + RETURN SinCos(x, ABS(x) + piByTwo, ONE) +END cos; + + +PROCEDURE tan* (x: REAL): REAL; +VAR + s, c: REAL; + +BEGIN + s := sin(x); + c := sqrt(ONE - s * s); + x := ABS(x) / (TWO * pi); + x := x - FLT(FLOOR(x)); + IF (0.25 < x) & (x < 0.75) THEN + c := -c + END + + RETURN s / c +END tan; + + +PROCEDURE arctan2* (y, x: REAL): REAL; +CONST + P0 = 0.216062307897242551884E+3; P1 = 0.3226620700132512059245E+3; + P2 = 0.13270239816397674701E+3; P3 = 0.1288838303415727934E+2; + Q0 = 0.2160623078972426128957E+3; Q1 = 0.3946828393122829592162E+3; + Q2 = 0.221050883028417680623E+3; Q3 = 0.3850148650835119501E+2; + Sqrt3 = 1.7320508075688772935E0; + +VAR + atan, z, z2, p, q: REAL; + yExp, xExp, Quadrant: INTEGER; + +BEGIN + IF ABS(x) < miny THEN + ASSERT(ABS(y) >= miny); + atan := piByTwo + ELSE + z := y; + UNPK(z, yExp); + z := x; + UNPK(z, xExp); + + IF yExp - xExp >= expoMax - 3 THEN + atan := piByTwo + ELSIF yExp - xExp < expoMin + 3 THEN + atan := ZERO + ELSE + IF ABS(y) > ABS(x) THEN + z := ABS(x / y); + Quadrant := 2 + ELSE + z := ABS(y / x); + Quadrant := 0 + END; + + IF z > TWO - Sqrt3 THEN + z := (z * Sqrt3 - ONE) / (Sqrt3 + z); + INC(Quadrant) + END; + + IF ABS(z) < Limit THEN + atan := z + ELSE + z2 := z * z; + p := (((P3 * z2 + P2) * z2 + P1) * z2 + P0) * z; + q := (((z2 + Q3) * z2 + Q2) * z2 + Q1) * z2 + Q0; + atan := p / q + END; + + CASE Quadrant OF + |0: + |1: atan := atan + pi / 6.0 + |2: atan := piByTwo - atan + |3: atan := pi / 3.0 - atan + END + END; + + IF x < ZERO THEN + atan := pi - atan + END + END; + + IF y < ZERO THEN + atan := -atan + END + + RETURN atan +END arctan2; + + +PROCEDURE arcsin* (x: REAL): REAL; +BEGIN + ASSERT(ABS(x) <= ONE) + RETURN arctan2(x, sqrt(ONE - x * x)) END arcsin; PROCEDURE arccos* (x: REAL): REAL; BEGIN - ASSERT(ABS(x) <= 1.0) - RETURN 0.5 * pi - arcsin(x) + ASSERT(ABS(x) <= ONE) + RETURN arctan2(sqrt(ONE - x * x), x) END arccos; PROCEDURE arctan* (x: REAL): REAL; - RETURN arcsin(x / sqrt(1.0 + x * x)) + RETURN arctan2(x, ONE) END arctan; PROCEDURE sinh* (x: REAL): REAL; BEGIN x := exp(x) - RETURN (x - 1.0 / x) * 0.5 + RETURN (x - ONE / x) * HALF END sinh; PROCEDURE cosh* (x: REAL): REAL; BEGIN x := exp(x) - RETURN (x + 1.0 / x) * 0.5 + RETURN (x + ONE / x) * HALF END cosh; PROCEDURE tanh* (x: REAL): REAL; BEGIN IF x > 15.0 THEN - x := 1.0 + x := ONE ELSIF x < -15.0 THEN - x := -1.0 + x := -ONE ELSE - x := exp(2.0 * x); - x := (x - 1.0) / (x + 1.0) + x := exp(TWO * x); + x := (x - ONE) / (x + ONE) END RETURN x @@ -244,21 +389,21 @@ END tanh; PROCEDURE arsinh* (x: REAL): REAL; - RETURN ln(x + sqrt(x * x + 1.0)) + RETURN ln(x + sqrt(x * x + ONE)) END arsinh; PROCEDURE arcosh* (x: REAL): REAL; BEGIN - ASSERT(x >= 1.0) - RETURN ln(x + sqrt(x * x - 1.0)) + ASSERT(x >= ONE) + RETURN ln(x + sqrt(x * x - ONE)) END arcosh; PROCEDURE artanh* (x: REAL): REAL; BEGIN - ASSERT(ABS(x) < 1.0) - RETURN 0.5 * ln((1.0 + x) / (1.0 - x)) + ASSERT(ABS(x) < ONE) + RETURN HALF * ln((ONE + x) / (ONE - x)) END artanh; @@ -267,9 +412,9 @@ VAR res: INTEGER; BEGIN - IF x > 0.0 THEN + IF x > ZERO THEN res := 1 - ELSIF x < 0.0 THEN + ELSIF x < ZERO THEN res := -1 ELSE res := 0 @@ -284,7 +429,7 @@ VAR res: REAL; BEGIN - res := 1.0; + res := ONE; WHILE n > 1 DO res := res * FLT(n); DEC(n) @@ -294,18 +439,42 @@ BEGIN END fact; -PROCEDURE init; +PROCEDURE DegToRad* (x: REAL): REAL; + RETURN x * (pi / 180.0) +END DegToRad; + + +PROCEDURE RadToDeg* (x: REAL): REAL; + RETURN x * (180.0 / pi) +END RadToDeg; + + +(* Return hypotenuse of triangle *) +PROCEDURE hypot* (x, y: REAL): REAL; VAR - i: INTEGER; + a: REAL; BEGIN - Exp[0] := 1.0; - FOR i := 1 TO LEN(Exp) - 1 DO - Exp[i] := Exp[i - 1] * e + x := ABS(x); + y := ABS(y); + IF x > y THEN + a := x * sqrt(1.0 + sqrr(y / x)) + ELSE + IF x > 0.0 THEN + a := y * sqrt(1.0 + sqrr(x / y)) + ELSE + a := y + END END -END init; + + RETURN a +END hypot; BEGIN - init + large := 1.9; + PACK(large, expoMax); + miny := ONE / large; + LnInfinity := ln(large); + LnSmall := ln(miny); END Math. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows64/Out.ob07 b/programs/develop/oberon07/Lib/Windows64/Out.ob07 index d75f9051e..3903c1117 100644 --- a/programs/develop/oberon07/Lib/Windows64/Out.ob07 +++ b/programs/develop/oberon07/Lib/Windows64/Out.ob07 @@ -1,308 +1,86 @@ (* - Copyright 2013, 2014, 2017, 2018, 2019 Anton Krotov + BSD 2-Clause License - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . + Copyright (c) 2020, Anton Krotov + All rights reserved. *) MODULE Out; -IMPORT sys := SYSTEM; +IMPORT SYSTEM; -CONST - - d = 1.0 - 5.0E-12; - -TYPE - - POverlapped* = POINTER TO OVERLAPPED; - - OVERLAPPED* = RECORD - - Internal*: INTEGER; - InternalHigh*: INTEGER; - Offset*: INTEGER; - OffsetHigh*: INTEGER; - hEvent*: INTEGER - - END; VAR - hConsoleOutput: INTEGER; - Realp: PROCEDURE (x: REAL; width: INTEGER); + hConsoleOutput: INTEGER; +PROCEDURE [windows, "msvcrt.dll", "printf"] printf1 (fmt: INTEGER; x: INTEGER); +PROCEDURE [windows, "msvcrt.dll", "printf"] printf2 (fmt: INTEGER; width, x: INTEGER); +PROCEDURE [windows, "msvcrt.dll", "printf"] printf3 (fmt: INTEGER; width, precision, x: INTEGER); -PROCEDURE [windows-, "kernel32.dll", "GetStdHandle"] +PROCEDURE [windows, "kernel32.dll", ""] + WriteConsoleW (hConsoleOutput, lpBuffer, nNumberOfCharsToWrite, lpNumberOfCharsWritten, lpReserved: INTEGER); + +PROCEDURE [windows, "kernel32.dll", ""] GetStdHandle (nStdHandle: INTEGER): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "WriteFile"] - WriteFile (hFile, Buffer, nNumberOfBytesToRead, lpNumberOfBytesRead: INTEGER; lpOverlapped: POverlapped): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "WriteConsoleW"] - WriteConsoleW (hConsoleOutput, lpBuffer, nNumberOfCharsToWrite, lpNumberOfCharsWritten, lpReserved: INTEGER): INTEGER; - - -PROCEDURE Char*(x: CHAR); -VAR count: INTEGER; +PROCEDURE Char* (x: CHAR); BEGIN - WriteFile(hConsoleOutput, sys.ADR(x), 1, sys.ADR(count), NIL) + printf1(SYSTEM.SADR("%c"), ORD(x)) END Char; -PROCEDURE StringW*(s: ARRAY OF WCHAR); -VAR count: INTEGER; + +PROCEDURE StringW* (s: ARRAY OF WCHAR); BEGIN - WriteConsoleW(hConsoleOutput, sys.ADR(s[0]), LENGTH(s), sys.ADR(count), 0) + WriteConsoleW(hConsoleOutput, SYSTEM.ADR(s[0]), LENGTH(s), 0, 0) END StringW; -PROCEDURE String*(s: ARRAY OF CHAR); -VAR len, i: INTEGER; + +PROCEDURE String* (s: ARRAY OF CHAR); BEGIN - len := LENGTH(s); - FOR i := 0 TO len - 1 DO - Char(s[i]) - END + printf2(SYSTEM.SADR("%.*s"), LENGTH(s), SYSTEM.ADR(s[0])) END String; -PROCEDURE WriteInt(x, n: INTEGER); -VAR i: INTEGER; a: ARRAY 32 OF CHAR; neg: BOOLEAN; -BEGIN - i := 0; - IF n < 1 THEN - n := 1 - END; - IF x < 0 THEN - x := -x; - DEC(n); - neg := TRUE - END; - REPEAT - a[i] := CHR(x MOD 10 + ORD("0")); - x := x DIV 10; - INC(i) - UNTIL x = 0; - WHILE n > i DO - Char(" "); - DEC(n) - END; - IF neg THEN - Char("-") - END; - REPEAT - DEC(i); - Char(a[i]) - UNTIL i = 0 -END WriteInt; - -PROCEDURE IsNan(AValue: REAL): BOOLEAN; -VAR s: SET; -BEGIN - sys.GET(sys.ADR(AValue), s) - RETURN (s * {52..62} = {52..62}) & ((s * {32..51} # {}) OR (s * {0..31} # {})) -END IsNan; - -PROCEDURE IsInf(x: REAL): BOOLEAN; - RETURN ABS(x) = sys.INF() -END IsInf; - -PROCEDURE Int*(x, width: INTEGER); -VAR i, minInt: INTEGER; -BEGIN - minInt := 1; - minInt := ROR(minInt, 1); - IF x # minInt THEN - WriteInt(x, width) - ELSE - FOR i := 21 TO width DO - Char(20X) - END; - String("-9223372036854775808") - END -END Int; - -PROCEDURE OutInf(x: REAL; width: INTEGER); -VAR s: ARRAY 5 OF CHAR; i: INTEGER; -BEGIN - IF IsNan(x) THEN - s := "Nan"; - INC(width) - ELSIF IsInf(x) & (x > 0.0) THEN - s := "+Inf" - ELSIF IsInf(x) & (x < 0.0) THEN - s := "-Inf" - END; - FOR i := 1 TO width - 4 DO - Char(" ") - END; - String(s) -END OutInf; PROCEDURE Ln*; BEGIN - Char(0DX); - Char(0AX) + printf1(SYSTEM.SADR("%s"), SYSTEM.SADR(CHR(13) + CHR(10))) END Ln; -PROCEDURE _FixReal(x: REAL; width, p: INTEGER); -VAR e, len, i: INTEGER; y: REAL; minus: BOOLEAN; -BEGIN - IF IsNan(x) OR IsInf(x) THEN - OutInf(x, width) - ELSIF p < 0 THEN - Realp(x, width) - ELSE - len := 0; - minus := FALSE; - IF x < 0.0 THEN - minus := TRUE; - INC(len); - x := ABS(x) - END; - e := 0; - WHILE x >= 10.0 DO - x := x / 10.0; - INC(e) - END; - IF e >= 0 THEN - len := len + e + p + 1; - IF x > 9.0 + d THEN - INC(len) - END; - IF p > 0 THEN - INC(len) - END; - ELSE - len := len + p + 2 - END; - FOR i := 1 TO width - len DO - Char(" ") - END; - IF minus THEN - Char("-") - END; - y := x; - WHILE (y < 1.0) & (y # 0.0) DO - y := y * 10.0; - DEC(e) - END; - IF e < 0 THEN - IF x - FLT(FLOOR(x)) > d THEN - Char("1"); - x := 0.0 - ELSE - Char("0"); - x := x * 10.0 - END - ELSE - WHILE e >= 0 DO - IF x - FLT(FLOOR(x)) > d THEN - IF x > 9.0 THEN - String("10") - ELSE - Char(CHR(FLOOR(x) + ORD("0") + 1)) - END; - x := 0.0 - ELSE - Char(CHR(FLOOR(x) + ORD("0"))); - x := (x - FLT(FLOOR(x))) * 10.0 - END; - DEC(e) - END - END; - IF p > 0 THEN - Char(".") - END; - WHILE p > 0 DO - IF x - FLT(FLOOR(x)) > d THEN - Char(CHR(FLOOR(x) + ORD("0") + 1)); - x := 0.0 - ELSE - Char(CHR(FLOOR(x) + ORD("0"))); - x := (x - FLT(FLOOR(x))) * 10.0 - END; - DEC(p) - END - END -END _FixReal; - -PROCEDURE Real*(x: REAL; width: INTEGER); -VAR e, n, i: INTEGER; minus: BOOLEAN; +PROCEDURE Int* (x, width: INTEGER); BEGIN - Realp := Real; - IF IsNan(x) OR IsInf(x) THEN - OutInf(x, width) - ELSE - e := 0; - n := 0; - IF width > 23 THEN - n := width - 23; - width := 23 - ELSIF width < 9 THEN - width := 9 - END; - width := width - 5; - IF x < 0.0 THEN - x := -x; - minus := TRUE - ELSE - minus := FALSE - END; - WHILE x >= 10.0 DO - x := x / 10.0; - INC(e) - END; - WHILE (x < 1.0) & (x # 0.0) DO - x := x * 10.0; - DEC(e) - END; - IF x > 9.0 + d THEN - x := 1.0; - INC(e) - END; - FOR i := 1 TO n DO - Char(" ") - END; - IF minus THEN - x := -x - END; - _FixReal(x, width, width - 3); - Char("E"); - IF e >= 0 THEN - Char("+") - ELSE - Char("-"); - e := ABS(e) - END; - IF e < 100 THEN - Char("0") - END; - IF e < 10 THEN - Char("0") - END; - Int(e, 0) - END + printf2(SYSTEM.SADR("%*lld"), width, x) +END Int; + + +PROCEDURE intval (x: REAL): INTEGER; +VAR + i: INTEGER; + +BEGIN + SYSTEM.GET(SYSTEM.ADR(x), i) + RETURN i +END intval; + + +PROCEDURE Real* (x: REAL; width: INTEGER); +BEGIN + printf3(SYSTEM.SADR("%*.*E"), width, MAX(MIN(width - 8, 15), 1), intval(x)) END Real; -PROCEDURE FixReal*(x: REAL; width, p: INTEGER); + +PROCEDURE FixReal* (x: REAL; width, precision: INTEGER); BEGIN - Realp := Real; - _FixReal(x, width, p) + printf3(SYSTEM.SADR("%*.*f"), width, precision, intval(x)) END FixReal; + PROCEDURE Open*; BEGIN hConsoleOutput := GetStdHandle(-11) END Open; + END Out. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows64/RTL.ob07 b/programs/develop/oberon07/Lib/Windows64/RTL.ob07 index 94a94eafd..7b6bbfb6a 100644 --- a/programs/develop/oberon07/Lib/Windows64/RTL.ob07 +++ b/programs/develop/oberon07/Lib/Windows64/RTL.ob07 @@ -350,33 +350,29 @@ END PCharToStr; PROCEDURE IntToStr (x: INTEGER; VAR str: ARRAY OF CHAR); VAR - i, a, b: INTEGER; - c: CHAR; + i, a: INTEGER; BEGIN i := 0; + a := x; REPEAT - str[i] := CHR(x MOD 10 + ORD("0")); - x := x DIV 10; - INC(i) - UNTIL x = 0; + INC(i); + a := a DIV 10 + UNTIL a = 0; - a := 0; - b := i - 1; - WHILE a < b DO - c := str[a]; - str[a] := str[b]; - str[b] := c; - INC(a); - DEC(b) - END; - str[i] := 0X + str[i] := 0X; + + REPEAT + DEC(i); + str[i] := CHR(x MOD 10 + ORD("0")); + x := x DIV 10 + UNTIL x = 0 END IntToStr; PROCEDURE append (VAR s1: ARRAY OF CHAR; s2: ARRAY OF CHAR); VAR - n1, n2, i, j: INTEGER; + n1, n2: INTEGER; BEGIN n1 := LENGTH(s1); @@ -384,19 +380,12 @@ BEGIN ASSERT(n1 + n2 < LEN(s1)); - i := 0; - j := n1; - WHILE i < n2 DO - s1[j] := s2[i]; - INC(i); - INC(j) - END; - - s1[j] := 0X + SYSTEM.MOVE(SYSTEM.ADR(s2[0]), SYSTEM.ADR(s1[n1]), n2); + s1[n1 + n2] := 0X END append; -PROCEDURE [stdcall64] _error* (module, err, line: INTEGER); +PROCEDURE [stdcall64] _error* (modnum, _module, err, line: INTEGER); VAR s, temp: ARRAY 1024 OF CHAR; @@ -415,10 +404,8 @@ BEGIN |11: s := "BYTE out of range" END; - append(s, API.eol); - - append(s, "module: "); PCharToStr(module, temp); append(s, temp); append(s, API.eol); - append(s, "line: "); IntToStr(line, temp); append(s, temp); + append(s, API.eol + "module: "); PCharToStr(_module, temp); append(s, temp); + append(s, API.eol + "line: "); IntToStr(line, temp); append(s, temp); API.DebugMsg(SYSTEM.ADR(s[0]), name); diff --git a/programs/develop/oberon07/Lib/Windows64/UnixTime.ob07 b/programs/develop/oberon07/Lib/Windows64/UnixTime.ob07 deleted file mode 100644 index 0e6ed5bd6..000000000 --- a/programs/develop/oberon07/Lib/Windows64/UnixTime.ob07 +++ /dev/null @@ -1,64 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2019, Anton Krotov - All rights reserved. -*) - -MODULE UnixTime; - - -VAR - - days: ARRAY 12, 31, 2 OF INTEGER; - - -PROCEDURE init; -VAR - i, j, k, n0, n1: INTEGER; -BEGIN - - FOR i := 0 TO 11 DO - FOR j := 0 TO 30 DO - days[i, j, 0] := 0; - days[i, j, 1] := 0; - END - END; - - days[ 1, 28, 0] := -1; - - FOR k := 0 TO 1 DO - days[ 1, 29, k] := -1; - days[ 1, 30, k] := -1; - days[ 3, 30, k] := -1; - days[ 5, 30, k] := -1; - days[ 8, 30, k] := -1; - days[10, 30, k] := -1; - END; - - n0 := 0; - n1 := 0; - FOR i := 0 TO 11 DO - FOR j := 0 TO 30 DO - IF days[i, j, 0] = 0 THEN - days[i, j, 0] := n0; - INC(n0) - END; - IF days[i, j, 1] = 0 THEN - days[i, j, 1] := n1; - INC(n1) - END - END - END - -END init; - - -PROCEDURE time* (year, month, day, hour, min, sec: INTEGER): INTEGER; - RETURN ((year - 1970) * 365 + days[month - 1, day - 1, ORD(year DIV 4 = 0)] + (year - 1969) DIV 4) * 86400 + hour * 3600 + min * 60 + sec -END time; - - -BEGIN - init -END UnixTime. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows64/WINAPI.ob07 b/programs/develop/oberon07/Lib/Windows64/WINAPI.ob07 index 86d166008..a6337b579 100644 --- a/programs/develop/oberon07/Lib/Windows64/WINAPI.ob07 +++ b/programs/develop/oberon07/Lib/Windows64/WINAPI.ob07 @@ -14,6 +14,10 @@ CONST OFS_MAXPATHNAME* = 128; + KERNEL = "kernel32.dll"; + USER = "user32.dll"; + MSVCRT = "msvcrt.dll"; + TYPE @@ -56,27 +60,59 @@ TYPE END; + tm* = RECORD + + sec*, + min*, + hour*, + mday*, + mon*, + year*, + wday*, + yday*, + isdst*: SYSTEM.CARD32 + + END; + PSecurityAttributes* = POINTER TO TSecurityAttributes; TSecurityAttributes* = RECORD - nLength*: INTEGER; + nLength*: SYSTEM.CARD32; lpSecurityDescriptor*: INTEGER; - bInheritHandle*: INTEGER + bInheritHandle*: SYSTEM.CARD32 (* BOOL *) END; TFileTime* = RECORD dwLowDateTime*, - dwHighDateTime*: INTEGER + dwHighDateTime*: SYSTEM.CARD32 + + END; + + TWin32FindData* = RECORD + + dwFileAttributes*: SYSTEM.CARD32; + ftCreationTime*: TFileTime; + ftLastAccessTime*: TFileTime; + ftLastWriteTime*: TFileTime; + nFileSizeHigh*: SYSTEM.CARD32; + nFileSizeLow*: SYSTEM.CARD32; + dwReserved0*: SYSTEM.CARD32; + dwReserved1*: SYSTEM.CARD32; + cFileName*: STRING; + cAlternateFileName*: ARRAY 14 OF CHAR; + dwFileType*: SYSTEM.CARD32; + dwCreatorType*: SYSTEM.CARD32; + wFinderFlags*: WCHAR END; OFSTRUCT* = RECORD - cBytes*: CHAR; - fFixedDisk*: CHAR; + cBytes*: BYTE; + fFixedDisk*: BYTE; nErrCode*: WCHAR; Reserved1*: WCHAR; Reserved2*: WCHAR; @@ -90,75 +126,93 @@ TYPE Internal*: INTEGER; InternalHigh*: INTEGER; - Offset*: INTEGER; - OffsetHigh*: INTEGER; + Offset*: SYSTEM.CARD32; + OffsetHigh*: SYSTEM.CARD32; hEvent*: INTEGER END; -PROCEDURE [windows-, "kernel32.dll", "SetConsoleCursorPosition"] - SetConsoleCursorPosition* (hConsoleOutput, dwCursorPosition: INTEGER): INTEGER; +PROCEDURE [windows-, KERNEL, ""] SetConsoleCursorPosition* (hConsoleOutput, dwCursorPosition: INTEGER): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "GetConsoleScreenBufferInfo"] - GetConsoleScreenBufferInfo* (hConsoleOutput: INTEGER; ConsoleScreenBufferInfo: TConsoleScreenBufferInfo): INTEGER; +PROCEDURE [windows-, KERNEL, ""] GetConsoleScreenBufferInfo* (hConsoleOutput: INTEGER; ConsoleScreenBufferInfo: TConsoleScreenBufferInfo): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "FillConsoleOutputCharacterA"] - FillConsoleOutputCharacter* (hConsoleOutput, cCaracter, nLength, dwWriteCoord, lpNumberOfCharsWritten: INTEGER): INTEGER; +PROCEDURE [windows-, KERNEL, ""] FillConsoleOutputCharacterA* (hConsoleOutput, cCaracter, nLength, dwWriteCoord, lpNumberOfCharsWritten: INTEGER): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "FillConsoleOutputAttribute"] - FillConsoleOutputAttribute* (hConsoleOutput, wAttribute, nLength, dwWriteCoord, lpNumberOfAttrsWritten: INTEGER): INTEGER; +PROCEDURE [windows-, KERNEL, ""] FillConsoleOutputAttribute* (hConsoleOutput, wAttribute, nLength, dwWriteCoord, lpNumberOfAttrsWritten: INTEGER): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "SetConsoleTextAttribute"] - SetConsoleTextAttribute* (hConsoleOutput, wAttributes: INTEGER): INTEGER; +PROCEDURE [windows-, KERNEL, ""] SetConsoleTextAttribute* (hConsoleOutput, wAttributes: INTEGER): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "GetStdHandle"] - GetStdHandle* (nStdHandle: INTEGER): INTEGER; +PROCEDURE [windows-, KERNEL, ""] GetStdHandle* (nStdHandle: INTEGER): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "CloseHandle"] - CloseHandle* (hObject: INTEGER): INTEGER; +PROCEDURE [windows-, KERNEL, ""] CloseHandle* (hObject: INTEGER): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "WriteFile"] - WriteFile* (hFile, Buffer, nNumberOfBytesToRead, lpNumberOfBytesRead: INTEGER; lpOverlapped: POverlapped): INTEGER; +PROCEDURE [windows-, KERNEL, ""] WriteFile* (hFile, Buffer, nNumberOfBytesToRead, lpNumberOfBytesRead: INTEGER; lpOverlapped: POverlapped): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "ReadFile"] - ReadFile* (hFile, Buffer, nNumberOfBytesToRead, lpNumberOfBytesRead: INTEGER; lpOverlapped: POverlapped): INTEGER; +PROCEDURE [windows-, KERNEL, ""] ReadFile* (hFile, Buffer, nNumberOfBytesToRead, lpNumberOfBytesRead: INTEGER; lpOverlapped: POverlapped): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "GetCommandLineA"] - GetCommandLine* (): INTEGER; +PROCEDURE [windows-, KERNEL, ""] GetCommandLineA* (): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "GlobalAlloc"] - GlobalAlloc* (uFlags, dwBytes: INTEGER): INTEGER; +PROCEDURE [windows-, KERNEL, ""] GlobalAlloc* (uFlags, dwBytes: INTEGER): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "GlobalFree"] - GlobalFree* (hMem: INTEGER): INTEGER; +PROCEDURE [windows-, KERNEL, ""] GlobalFree* (hMem: INTEGER): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "ExitProcess"] - ExitProcess* (code: INTEGER); +PROCEDURE [windows-, KERNEL, ""] ExitProcess* (code: INTEGER); -PROCEDURE [windows-, "kernel32.dll", "GetTickCount"] - GetTickCount* (): INTEGER; +PROCEDURE [windows-, KERNEL, ""] GetTickCount* (): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "Sleep"] - Sleep* (dwMilliseconds: INTEGER); +PROCEDURE [windows-, KERNEL, ""] Sleep* (dwMilliseconds: INTEGER); -PROCEDURE [windows-, "kernel32.dll", "FreeLibrary"] - FreeLibrary* (hLibModule: INTEGER): INTEGER; +PROCEDURE [windows-, KERNEL, ""] FreeLibrary* (hLibModule: INTEGER): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "GetProcAddress"] - GetProcAddress* (hModule, name: INTEGER): INTEGER; +PROCEDURE [windows-, KERNEL, ""] GetProcAddress* (hModule, name: INTEGER): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "LoadLibraryA"] - LoadLibraryA* (name: INTEGER): INTEGER; +PROCEDURE [windows-, KERNEL, ""] LoadLibraryA* (name: INTEGER): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "AllocConsole"] - AllocConsole* (): BOOLEAN; +PROCEDURE [windows-, KERNEL, ""] AllocConsole* (): BOOLEAN; -PROCEDURE [windows-, "kernel32.dll", "FreeConsole"] - FreeConsole* (): BOOLEAN; +PROCEDURE [windows-, KERNEL, ""] FreeConsole* (): BOOLEAN; -PROCEDURE [windows-, "kernel32.dll", "GetLocalTime"] - GetLocalTime* (T: TSystemTime); +PROCEDURE [windows-, KERNEL, ""] GetLocalTime* (T: TSystemTime); + +PROCEDURE [windows-, KERNEL, ""] RemoveDirectoryA* (lpPathName: INTEGER): INTEGER; + +PROCEDURE [windows-, KERNEL, ""] GetFileAttributesA* (lpPathName: INTEGER): SET; + +PROCEDURE [windows-, KERNEL, ""] CreateDirectoryA* (lpPathName: INTEGER; lpSecurityAttributes: PSecurityAttributes): INTEGER; + +PROCEDURE [windows-, KERNEL, ""] FindFirstFileA* (lpFileName: INTEGER; lpFindFileData: TWin32FindData): INTEGER; + +PROCEDURE [windows-, KERNEL, ""] DeleteFileA* (lpFileName: INTEGER): INTEGER; + +PROCEDURE [windows-, KERNEL, ""] FindClose* (hFindFile: INTEGER): INTEGER; + +PROCEDURE [windows-, KERNEL, ""] CreateFileA* ( + lpFileName, dwDesiredAccess, dwShareMode: INTEGER; + lpSecurityAttributes: PSecurityAttributes; + dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile: INTEGER): INTEGER; + +PROCEDURE [windows-, KERNEL, ""] OpenFile* (lpFileName: INTEGER; lpReOpenBuff: OFSTRUCT; uStyle: INTEGER): INTEGER; + +PROCEDURE [windows-, KERNEL, ""] SetFilePointer* (hFile, lDistanceToMove, lpDistanceToMoveHigh, dwMoveMethod: INTEGER): INTEGER; + +PROCEDURE [windows-, KERNEL, ""] ReadConsoleA* (hConsoleInput, lpBuffer, nNumberOfCharsToRead, lpNumberOfCharsRead, lpReserved: INTEGER): INTEGER; + +PROCEDURE [windows-, KERNEL, ""] WriteConsoleW* (hConsoleOutput, lpBuffer, nNumberOfCharsToWrite, lpNumberOfCharsWritten, lpReserved: INTEGER): INTEGER; + +PROCEDURE [windows-, KERNEL, ""] WriteConsoleA* (hConsoleOutput, lpBuffer, nNumberOfCharsToWrite, lpNumberOfCharsWritten, lpReserved: INTEGER): INTEGER; + +PROCEDURE [windows-, USER, ""] MessageBoxA* (hWnd, lpText, lpCaption, uType: INTEGER): INTEGER; + +PROCEDURE [windows-, USER, ""] MessageBoxW* (hWnd, lpText, lpCaption, uType: INTEGER): INTEGER; + +PROCEDURE [windows-, USER, ""] CreateWindowExA* ( + dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, + nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam: INTEGER): INTEGER; + +PROCEDURE [windows-, MSVCRT, ""] time* (ptr: INTEGER): INTEGER; + +PROCEDURE [windows-, MSVCRT, ""] mktime* (time: tm): INTEGER; PROCEDURE SetDllEntry* (process_detach, thread_detach, thread_attach: DLL_ENTRY); diff --git a/programs/develop/oberon07/Samples/Dialogs.ob07 b/programs/develop/oberon07/Samples/KolibriOS/Dialogs.ob07 similarity index 100% rename from programs/develop/oberon07/Samples/Dialogs.ob07 rename to programs/develop/oberon07/Samples/KolibriOS/Dialogs.ob07 diff --git a/programs/develop/oberon07/Samples/HW.ob07 b/programs/develop/oberon07/Samples/KolibriOS/HW.ob07 similarity index 100% rename from programs/develop/oberon07/Samples/HW.ob07 rename to programs/develop/oberon07/Samples/KolibriOS/HW.ob07 diff --git a/programs/develop/oberon07/Samples/HW_con.ob07 b/programs/develop/oberon07/Samples/KolibriOS/HW_con.ob07 similarity index 100% rename from programs/develop/oberon07/Samples/HW_con.ob07 rename to programs/develop/oberon07/Samples/KolibriOS/HW_con.ob07 diff --git a/programs/develop/oberon07/Samples/Linux/HW.ob07 b/programs/develop/oberon07/Samples/Linux/HW.ob07 new file mode 100644 index 000000000..382ab9ca2 --- /dev/null +++ b/programs/develop/oberon07/Samples/Linux/HW.ob07 @@ -0,0 +1,52 @@ +MODULE HW; + +IMPORT SYSTEM, Libdl, Args; + + +VAR + + libc: INTEGER; + puts: PROCEDURE [linux] (pStr: INTEGER); + + +PROCEDURE OutStringLn (s: ARRAY OF CHAR); +BEGIN + puts(SYSTEM.ADR(s[0])) +END OutStringLn; + + +PROCEDURE main; +VAR + i: INTEGER; + s: ARRAY 80 OF CHAR; + +BEGIN + OutStringLn("Hello"); + + OutStringLn(""); + i := 0; + WHILE i < Args.argc DO + Args.GetArg(i, s); + INC(i); + OutStringLn(s) + END; + + OutStringLn(""); + i := 0; + WHILE i < Args.envc DO + Args.GetEnv(i, s); + INC(i); + OutStringLn(s) + END; + OutStringLn(""); + + OutStringLn("Bye") +END main; + + +BEGIN + libc := Libdl.open("libc.so.6", Libdl.LAZY); + SYSTEM.PUT(SYSTEM.ADR(puts), Libdl.sym(libc, "puts")); + ASSERT(puts # NIL); + main +END HW. diff --git a/programs/develop/oberon07/Samples/Linux/X11/animation/_unix.ob07 b/programs/develop/oberon07/Samples/Linux/X11/animation/_unix.ob07 new file mode 100644 index 000000000..0cd77749e --- /dev/null +++ b/programs/develop/oberon07/Samples/Linux/X11/animation/_unix.ob07 @@ -0,0 +1,74 @@ +MODULE _unix; (* connect to unix host *) +IMPORT SYSTEM, API; + +(* how to find C declarations: +- gcc -E preprocess only (to stdout) (preprocessor expand) +- grep -r name /usr/include/* +- ldd progfile +- objdump -T progfile (-t) (-x) +*) + +CONST RTLD_LAZY = 1; + BIT_DEPTH* = API.BIT_DEPTH; + +VAR sym, libc, libdl :INTEGER; + + _dlopen* :PROCEDURE [linux] (name, flags :INTEGER) :INTEGER; + _dlsym* :PROCEDURE [linux] (p, name :INTEGER) :INTEGER; + _dlclose* :PROCEDURE [linux] (p :INTEGER) :INTEGER; + _open* :PROCEDURE [linux] (name, flags, mode :INTEGER) :INTEGER; + _close* :PROCEDURE [linux] (fd :INTEGER) :INTEGER; + _read* :PROCEDURE [linux] (fd, buf, sz :INTEGER): INTEGER; + _write* :PROCEDURE [linux] (fd, buf, sz :INTEGER) :INTEGER; + _exit* :PROCEDURE [linux] (n :INTEGER); + _malloc* :PROCEDURE [linux] (sz :INTEGER) :INTEGER; + _select* :PROCEDURE [linux] (cnt, readfds, writefds, exceptfds, timeout :INTEGER) :INTEGER; + + (* error message to stderr *) +PROCEDURE writeChar (c :CHAR); +VAR ri :INTEGER; +BEGIN ri := _write (2, SYSTEM.ADR(c), 1); ASSERT (ri = 1) END writeChar; + +PROCEDURE writeString (s :ARRAY OF CHAR); +VAR i :INTEGER; +BEGIN i := 0; WHILE s[i] # 0X DO writeChar (s[i]); INC(i) END; END writeString; + +PROCEDURE nl; +BEGIN writeChar (0AX) END nl; + + +PROCEDURE getSymAdr (lib :INTEGER; name :ARRAY OF CHAR; adr :INTEGER); +BEGIN + sym := _dlsym (lib, SYSTEM.ADR(name[0])); + IF sym = 0 THEN writeString ("error: dlsym: "); writeString (name); nl END; + ASSERT (sym # 0); + SYSTEM.PUT (adr, sym) +END getSymAdr; + + +PROCEDURE finish*; +VAR ri :INTEGER; +BEGIN + IF libc # 0 THEN ri := _dlclose (libc); libc := 0 END; + IF libdl # 0 THEN ri := _dlclose (libdl); libdl := 0 END; +END finish; + + +BEGIN + _dlopen := API.dlopen; + _dlsym := API.dlsym; + libc := _dlopen (SYSTEM.SADR("libc.so.6"), RTLD_LAZY); ASSERT (libc # 0); + (* getSymAdr is not used for write() to get writeString() error message going *); + sym := _dlsym (libc, SYSTEM.SADR("write")); ASSERT (sym # 0); SYSTEM.PUT (SYSTEM.ADR(_write), sym); + + libdl := _dlopen (SYSTEM.SADR("libdl.so.2"), RTLD_LAZY); ASSERT (libdl # 0); + getSymAdr (libdl, "dlclose", SYSTEM.ADR(_dlclose)); + + getSymAdr (libc, "open", SYSTEM.ADR(_open)); + getSymAdr (libc, "close", SYSTEM.ADR(_close)); + getSymAdr (libc, "read", SYSTEM.ADR(_read)); + getSymAdr (libc, "exit", SYSTEM.ADR(_exit)); + getSymAdr (libc, "malloc", SYSTEM.ADR(_malloc)); + getSymAdr (libc, "select", SYSTEM.ADR(_select)); +END _unix. + diff --git a/programs/develop/oberon07/Samples/Linux/X11/animation/animation.ob07 b/programs/develop/oberon07/Samples/Linux/X11/animation/animation.ob07 new file mode 100644 index 000000000..eaf840334 --- /dev/null +++ b/programs/develop/oberon07/Samples/Linux/X11/animation/animation.ob07 @@ -0,0 +1,89 @@ +MODULE animation; (* moving turtle example *) +(* demonstrates use of timeout and select() to display a moving turtle in an X11 window *) +IMPORT SYSTEM, gr; + +CONST + Side = 8; (* nr of pixels of a square side *) + +VAR base, stride, screenBufSize :INTEGER; + currentX :INTEGER; + + +PROCEDURE drawSquare (x, y, color :INTEGER); +VAR p, i, j :INTEGER; +BEGIN + p := (y*stride + x*4)*Side; + ASSERT (p + (Side-1)*stride + (Side-1)*4 <= screenBufSize); + p := base + p; + FOR j := 0 TO Side-1 DO + FOR i := 0 TO Side-1 DO SYSTEM.PUT32 (p, color); INC(p, 4) END; + p := p + stride - Side*4; + END; +END drawSquare; + + +PROCEDURE putLine (x : INTEGER; y: INTEGER;str : ARRAY OF CHAR); +VAR z, x1: INTEGER; +BEGIN + FOR z := 0 TO LEN(str) - 1 DO + x1 := (x + z) MOD 100; + IF str[z] = "b" THEN drawSquare(x1, y, 0600000H); END; (* brown *) + IF str[z] = "g" THEN drawSquare(x1, y, 000C000H); END; (* green *) + END; +END putLine; + + +PROCEDURE turtlePicture (x , y : INTEGER); +BEGIN + putLine(x, y + 0 , "....bb........"); + putLine(x, y + 1 , "....bbb......."); + putLine(x, y + 2 , "....bbbb......"); + putLine(x, y + 3 , ".bb..bbb......"); + putLine(x, y + 4 , ".bgggbbbgbbgb."); + putLine(x, y + 5 , ".ggggggggbbbb."); + putLine(x, y + 6 , "bggggggggbbbb."); + putLine(x, y + 7 , ".ggggggg......"); + putLine(x, y + 8 , ".bb..bbb......"); + putLine(x, y + 9 , "....bbbb......"); + putLine(x, y + 10, ".....bbb......"); + putLine(x, y + 11, ".....bb.......") +END turtlePicture; + + +PROCEDURE drawAll; +BEGIN + gr.screenBegin; + gr.clear (0C0F0FFH); (* light blue *) + turtlePicture (currentX, 15); + gr.screenEnd; +END drawAll; + + +PROCEDURE run*; +VAR stop :BOOLEAN; + ev :gr.EventPars; + ch :CHAR; +BEGIN + base := gr.base; stride := gr.stride; + gr.createWindow (800, 480); + screenBufSize := gr.winHeight * stride; + stop := FALSE; currentX := 15; + drawAll; + REPEAT + gr.nextEvent (400, ev); + IF ev[0] = gr.EventTimeOut THEN + drawAll; + INC (currentX, 4); + ELSIF ev[0] = gr.EventKeyPressed THEN + ch := CHR(ev[4]); + IF (ch = "q") OR (ch = 0AX) OR (ch = " ") THEN stop := TRUE END; + IF ev[2] = 9 (* ESC *) THEN stop := TRUE END; + END; + UNTIL stop; + gr.finish; +END run; + +BEGIN + run; +END animation. + diff --git a/programs/develop/oberon07/Samples/Linux/X11/animation/gr.ob07 b/programs/develop/oberon07/Samples/Linux/X11/animation/gr.ob07 new file mode 100644 index 000000000..c22e75e82 --- /dev/null +++ b/programs/develop/oberon07/Samples/Linux/X11/animation/gr.ob07 @@ -0,0 +1,292 @@ +MODULE gr; (* connect to libX11 *) +IMPORT SYSTEM, unix, out; + +(* +X11 documentation in: +- http://tronche.com/gui/x/xlib/ an X11 reference +- http://www.sbin.org/doc/Xlib an X11 tutorial (this domain has disappeared) +*) + +CONST + InputOutput = 1; + StructureNotifyMask = 20000H; (* input event mask *) + ExposureMask = 8000H; KeyPressMask = 1; KeyReleaseMask = 2; + ButtonPressMask = 4; ButtonReleaseMask = 8; (* PointerNotionMask *) + ZPixmap = 2; + Expose = 12; (* X event type *) ConfigureNotify = 22; KeyPress = 2; ButtonPress = 4; + + EventTimeOut* = 80; (* 0, 0, 0, 0 *) + EventResize* = 81; (* 0, w, h, 0 *) + EventKeyPressed* = 82; (* isPrintable, keyCode (X11 scan code), state, keySym (ASCII) *) + EventKeyReleased* = 83; (* 0, keyCode, state, 0 *) + EventButtonPressed* = 84; (* button, x, y, state *) + EventButtonReleased* = 85; (* button, x, y, state *) + (* mouse button 1-5 = Left, Middle, Right, Scroll wheel up, Scroll wheel down *) + + bit64 = ORD(unix.BIT_DEPTH = 64); + +TYPE EventPars* = ARRAY 5 OF INTEGER; + XEvent = RECORD + val :ARRAY 192 OF BYTE (* union { ..., long pad[24]; } *) + (* val :ARRAY 48 OF CARD32; *) + END; + +VAR ScreenWidth*, ScreenHeight* :INTEGER; + winWidth*, winHeight* :INTEGER; (* draw by writing to pixel buffer: *) + base*, stride* :INTEGER; (* width, height, base ptr, stride in bytes, 32-bit RGB *) + painting :BOOLEAN; + + libX11 :INTEGER; (* handle to dynamic library *) + XOpenDisplay :PROCEDURE [linux] (name :INTEGER) :INTEGER; + XCloseDisplay :PROCEDURE [linux] (display :INTEGER); + XSynchronize :PROCEDURE [linux] (display, onoff :INTEGER) :INTEGER; (* return prev onoff *) + XConnectionNumber :PROCEDURE [linux] (display :INTEGER) :INTEGER; + XCreateWindow :PROCEDURE [linux] (display, parent_window, x, y, w, h, border_width, depth, + class, visual, valuemask, attributes :INTEGER) :INTEGER; (* Window *) + XDefaultScreen :PROCEDURE [linux] (display :INTEGER) :INTEGER; + XDefaultGC :PROCEDURE [linux] (display, screenNr :INTEGER) :INTEGER; (* GC *) + XDisplayWidth :PROCEDURE [linux] (display, screenNr :INTEGER) :INTEGER; + XDisplayHeight :PROCEDURE [linux] (display, screenNr :INTEGER) :INTEGER; + XDefaultVisual :PROCEDURE [linux] (display, screenNr :INTEGER) :INTEGER; (* visual *) + XDefaultRootWindow :PROCEDURE [linux] (display :INTEGER) :INTEGER; (* Window *) + XDefaultDepth :PROCEDURE [linux] (display, screenNr :INTEGER) :INTEGER; + XSelectInput :PROCEDURE [linux] (display, window, event_mask :INTEGER); + XMapWindow :PROCEDURE [linux] (display, window :INTEGER); + XNextEvent :PROCEDURE [linux] (display, XEvent_p :INTEGER); + XPending :PROCEDURE [linux] (display :INTEGER) :INTEGER; + XLookupString :PROCEDURE [linux] (key_event, buffer_return, buflen, keysym_return, status_in_out :INTEGER) :INTEGER; + XCreateImage :PROCEDURE [linux] (display, visual, depth, format, offset, data, + width, height, bitmap_pad, bytes_per_line :INTEGER) :INTEGER; (* ptr to XImage *) + XPutImage :PROCEDURE [linux] (display, window, gc, image, sx, sy, dx, dy, w, h :INTEGER); + + display, screen, window, gc, img :INTEGER; + connectionNr :INTEGER; (* fd of X11 socket *) + readX11 :unix.fd_set; (* used by select() timeout on X11 socket *) + + +PROCEDURE getSymAdr (lib :INTEGER; name :ARRAY OF CHAR; adr :INTEGER); +VAR sym :INTEGER; +BEGIN + sym := unix.dlsym (lib, SYSTEM.ADR(name[0])); + IF sym = 0 THEN out.formatStr ("error: dlsym: %", name); out.nl END; + ASSERT (sym # 0); + SYSTEM.PUT (adr, sym) +END getSymAdr; + + +PROCEDURE init; +BEGIN + display := XOpenDisplay (0); + IF display = 0 THEN out.str ("error: can not open X11 display."); out.nl; out.exit(1) END; + (* ri := XSynchronize (display, 1); *) + connectionNr := XConnectionNumber (display); ASSERT (connectionNr < unix.FD_SETSIZE); + NEW (readX11); unix.FD_ZERO(readX11); unix.FD_SET (connectionNr, readX11); + screen := XDefaultScreen (display); gc := XDefaultGC (display, screen); + ScreenWidth := XDisplayWidth (display, screen); ScreenHeight := XDisplayHeight (display, screen); + base := unix.malloc (ScreenWidth * ScreenHeight * 4); + IF base = 0 THEN + out.formatInt2 ("error: can not allocate screen buffer % x %", ScreenWidth, ScreenHeight); out.nl; out.exit(1); + END; + stride := ScreenWidth * 4; + img := XCreateImage (display, XDefaultVisual (display, screen), XDefaultDepth (display, screen), + ZPixmap, 0, base, ScreenWidth, ScreenHeight, 32, 0); +END init; + + +PROCEDURE finish*; +VAR ri :INTEGER; +BEGIN + IF display # 0 THEN XCloseDisplay(display); display := 0 END; + IF libX11 # 0 THEN ri := unix.dlclose (libX11); libX11 := 0 END; +END finish; + + +PROCEDURE createWindow* (w, h :INTEGER); +VAR eventMask :INTEGER; +BEGIN + IF (w > ScreenWidth) OR (h > ScreenHeight) THEN + out.str ("error: X11.createWindow: window too large"); out.exit(1); + END; + ASSERT ((w >= 0) & (h >= 0)); + window := XCreateWindow (display, XDefaultRootWindow (display), 0, 0, w, h, 0, + XDefaultDepth (display, screen), InputOutput, XDefaultVisual (display, screen), 0, 0); + winWidth := w; winHeight := h; + eventMask := StructureNotifyMask + ExposureMask + KeyPressMask + ButtonPressMask; + XSelectInput (display, window, eventMask); + XMapWindow (display, window); +END createWindow; + + +PROCEDURE screenBegin*; + (* intended to enable future cooperation with iOS / MacOS *) +BEGIN + ASSERT (~painting); painting := TRUE +END screenBegin; + + +PROCEDURE screenEnd*; +BEGIN + ASSERT (painting); + XPutImage (display, window, gc, img, 0, 0, 0, 0, winWidth, winHeight); + painting := FALSE; +END screenEnd; + + +PROCEDURE readInt (e :XEvent; i :INTEGER) :INTEGER; + (* treat XEvent byte array as int array *) +VAR n :INTEGER; +BEGIN + ASSERT (i >= 0); + ASSERT (i < 48); + i := i * 4; + n := e.val[i+3]*1000000H + e.val[i+2]*10000H + e.val[i+1]*100H + e.val[i]; +RETURN n +END readInt; + + +PROCEDURE nextEvent* (msTimeOut :INTEGER; VAR ev :EventPars); +VAR _type, n, ri :INTEGER; + event :XEvent; + x, y, w, h :INTEGER; + timeout :unix.timespec; +BEGIN +(* struct XEvent (64-bit): +any: 4 type 8 serial 4 send_event 8 display 8 window 8 window +expose: 40 any 4 x, y, w, h, count +xconfigure: 48 any 4 x, y, w, h +xkey / xbutton / xmotion: 48 any 8 sub_window 8 time_ms 4 x, y, x_root, y_root 4 state 4 keycode/button +*) +(* struct XEvent (32-bit): +any: 4 type 4 serial 4 send_event 4 display 4 window +expose: 20 any 4 x, y, w, h, count +xconfigure: 24 any 4 x, y, w, h +xkey / xbutton / xmotion: 24 any 4 sub_window 4 time_ms 4 x, y, x_root, y_root 4 state 4 keycode/button +*) + _type := 0; + WHILE _type = 0 DO + IF (msTimeOut > 0) & (XPending(display) = 0) THEN + timeout.tv_sec := msTimeOut DIV 1000; timeout.tv_usec := (msTimeOut MOD 1000) * 1000; + ri := unix.select (connectionNr + 1, readX11, NIL, NIL, timeout); ASSERT (ri # -1); + IF ri = 0 THEN _type := EventTimeOut; ev[1] := 0; ev[2] := 0; ev[3] := 0; ev[4] := 0 END; + END; + IF _type = 0 THEN + XNextEvent (display, SYSTEM.ADR(event)); + CASE readInt (event, 0) OF + Expose : + x := readInt (event, 5 + 5 * bit64); y := readInt (event, 6 + 5 * bit64); + w := readInt (event, 7 + 5 * bit64); h := readInt (event, 8 + 5 * bit64); + XPutImage (display, window, gc, img, x, y, x, y, w, h); + | ConfigureNotify : + w := readInt (event, 8 + 6 * bit64); h := readInt (event, 9 + 6 * bit64); + IF (w # winWidth) & (h # winHeight) THEN + ASSERT ((w >= 0) & (h >= 0)); + IF w > ScreenWidth THEN w := ScreenWidth END; + IF h > ScreenHeight THEN h := ScreenHeight END; + winWidth := w; winHeight := h; + ev[0] := EventResize; ev[1] := 0; ev[2] := w; ev[3] := h; ev[4] := 0; + END; + | KeyPress : + _type := EventKeyPressed; + x := XLookupString (SYSTEM.ADR(event), 0, 0, SYSTEM.ADR(n), 0); (* KeySym *) + IF (n = 8) OR (n = 10) OR (n >= 32) & (n <= 126) THEN ev[1] := 1 ELSE ev[1] := 0; n := 0 END; (* isprint *) + ev[2] := readInt (event, 13 + 8 * bit64); (* keycode *) + ev[3] := readInt (event, 12 + 8 * bit64); (* state *) + ev[4] := n; (* KeySym *) + | ButtonPress : + _type := EventButtonPressed; + ev[1] := readInt (event, 13 + 8 * bit64); (* button *) + ev[2] := readInt (event, 8 + 8 * bit64); (* x *) + ev[3] := readInt (event, 9 + 8 * bit64); (* y *) + ev[4] := readInt (event, 12 + 8 * bit64); (* state *) + ELSE + END + END + END; + ev[0] := _type +END nextEvent; + + +PROCEDURE clear* (color :INTEGER); (* fill window area with color *) +VAR p, i, j :INTEGER; +BEGIN + FOR j := 0 TO winHeight-1 DO + p := base + j*stride; + FOR i := 0 TO winWidth-1 DO SYSTEM.PUT32 (p, color); INC (p, 4) END + END +END clear; + + +(* +PROCEDURE blitError (stride, x, y, w, h :INTEGER); +BEGIN + o.formatInt ("error: screen.blit (src, %)", stride); + o.formatInt2 (", %, %", x, y); + o.formatInt2 (", %, %) out of bounds", w, h); o.nl; + ASSERT (FALSE) +END blitError; + +PROCEDURE blit* (src, srcStride, x, y, w, h :INTEGER); +VAR dstStride, p :INTEGER; +BEGIN + IF (x < 0) OR (y < 0) THEN blitError (srcStride, x, y, w, h) END; + IF (w <= 0) OR (h <= 0) THEN blitError (srcStride, x, y, w, h) END; + IF (x + w > ScreenWidth) OR (y + h > ScreenHeight) THEN blitError (srcStride, x, y, w, h) END; + + dstStride := ScreenWidth - w; + p := ScreenBase + y * ScreenWidth + x * 4; + REPEAT + SYSTEM.COPY (src, p, w); + INC (src, srcStride); INC (p, dstStride); DEC (h) + UNTIL h = 0 +END blit; +*) + +(* +PROCEDURE setPixel* (x, y, color :INTEGER); +VAR p :INTEGER; +BEGIN + ASSERT ((x >= 0) & (x < ScreenWidth) & (y >= 0) & (y < ScreenHeight)); + screenBegin; p := base + (y*ScreenWidth + x)*4; SYSTEM.PUT32 (p, color); p := p + 4 screenEnd +END setPixel; +*) + +(* +PROCEDURE loop; (* example main loop *) +VAR e :EventPars; + stop :BOOLEAN; +BEGIN + createWindow (200, 200); + stop := FALSE; + REPEAT + nextEvent (0, e); + IF e[0] = EventKeyPressed THEN stop := TRUE END; + UNTIL stop; + XCloseDisplay (display); +END loop; +*) + + +BEGIN + libX11 := unix.dlopen (SYSTEM.SADR("libX11.so.6"), unix.RTLD_LAZY); ASSERT (libX11 # 0); + getSymAdr (libX11, "XOpenDisplay", SYSTEM.ADR(XOpenDisplay)); + getSymAdr (libX11, "XCloseDisplay", SYSTEM.ADR(XCloseDisplay)); + getSymAdr (libX11, "XSynchronize", SYSTEM.ADR(XSynchronize)); + getSymAdr (libX11, "XConnectionNumber", SYSTEM.ADR(XConnectionNumber)); + getSymAdr (libX11, "XCreateWindow", SYSTEM.ADR(XCreateWindow)); + getSymAdr (libX11, "XDefaultScreen", SYSTEM.ADR(XDefaultScreen)); + getSymAdr (libX11, "XDefaultGC", SYSTEM.ADR(XDefaultGC)); + getSymAdr (libX11, "XDisplayWidth", SYSTEM.ADR(XDisplayWidth)); + getSymAdr (libX11, "XDisplayHeight", SYSTEM.ADR(XDisplayHeight)); + getSymAdr (libX11, "XDefaultVisual", SYSTEM.ADR(XDefaultVisual)); + getSymAdr (libX11, "XDefaultRootWindow", SYSTEM.ADR(XDefaultRootWindow)); + getSymAdr (libX11, "XDefaultDepth", SYSTEM.ADR(XDefaultDepth)); + getSymAdr (libX11, "XSelectInput", SYSTEM.ADR(XSelectInput)); + getSymAdr (libX11, "XMapWindow", SYSTEM.ADR(XMapWindow)); + getSymAdr (libX11, "XNextEvent", SYSTEM.ADR(XNextEvent)); + getSymAdr (libX11, "XPending", SYSTEM.ADR(XPending)); + getSymAdr (libX11, "XLookupString", SYSTEM.ADR(XLookupString)); + getSymAdr (libX11, "XCreateImage", SYSTEM.ADR(XCreateImage)); + getSymAdr (libX11, "XPutImage", SYSTEM.ADR(XPutImage)); + init; +END gr. + diff --git a/programs/develop/oberon07/Samples/Linux/X11/animation/out.ob07 b/programs/develop/oberon07/Samples/Linux/X11/animation/out.ob07 new file mode 100644 index 000000000..ad8478ce9 --- /dev/null +++ b/programs/develop/oberon07/Samples/Linux/X11/animation/out.ob07 @@ -0,0 +1,142 @@ +MODULE out; (* formatted output to stdout *) +(* Wim Niemann, Jan Tuitman 06-OCT-2016 *) + +IMPORT SYSTEM, _unix; + +(* example: IMPORT o:=out; + o.str("Hello, World!");o.nl; + o.formatInt("n = %", 3);o.nl; +*) + +(* +The output functions buffer the characters in buf. This buffer is flushed when out.nl is +called and also when the buffer is full. + +Calling flush once per line is far more efficient then one system call per +character, but this is noticable only at very long outputs. +*) + +CONST MAX = 63; (* last position in buf *) + +VAR len :INTEGER; (* string length in buf *) + buf :ARRAY MAX+1 OF BYTE; + +PROCEDURE exit* (n :INTEGER); + (* prevent IMPORT unix for many programs *) +BEGIN _unix._exit(n) END exit; + +PROCEDURE writeChars; + (* write buf to the output function and set to empty string *) +VAR ri :INTEGER; +BEGIN + IF len > 0 THEN + (* buf[len] := 0X; *) + ri := _unix._write (1, SYSTEM.ADR(buf), len); ASSERT (ri = len); (* stdout *) + len := 0 + END +END writeChars; + +PROCEDURE nl*; (* append a newline to buf and flush *) +BEGIN + IF len = MAX THEN writeChars END; + buf[len] := 0AH; INC(len); + (* unix: 0AX; Oberon: 0DX; + Windows: IF len >= MAX-1 THEN 0DX 0AX; *) + writeChars; +END nl; + +PROCEDURE char* (c :CHAR); + (* append char to the end of buf *) +BEGIN + IF len = MAX THEN writeChars END; + buf[len] := ORD(c); INC(len) +END char; + +PROCEDURE str* (t :ARRAY OF CHAR); + (* append t to buf *) +VAR j :INTEGER; +BEGIN + j := 0; WHILE t[j] # 0X DO char(t[j]); INC(j) END +END str; + +PROCEDURE int* (n :INTEGER); + (* append integer; append n to d, return TRUE on overflow of d *) +VAR j :INTEGER; + sign :BOOLEAN; + dig :ARRAY 11 OF CHAR; (* assume 32 bit INTEGER *) +BEGIN + sign := FALSE; IF n < 0 THEN sign := TRUE; n := -n END; + IF n < 0 THEN + str ("-2147483648"); + ELSE + j := 0; + REPEAT dig[j] := CHR (n MOD 10 + 30H); n := n DIV 10; INC(j) UNTIL n = 0; + IF sign THEN char ("-") END; + REPEAT DEC(j); char(dig[j]) UNTIL j = 0; + END +END int; + +PROCEDURE formatInt* (t :ARRAY OF CHAR; n :INTEGER); + (* append formatted string t. Replace the first % by n *) +VAR j :INTEGER; +BEGIN + j := 0; WHILE (t[j] # 0X) & (t[j] # "%") DO char(t[j]); INC(j) END; + IF t[j] = "%" THEN + int(n); INC(j); + WHILE t[j] # 0X DO char(t[j]); INC(j) END + END +END formatInt; + +PROCEDURE formatInt2* (t:ARRAY OF CHAR; n1, n2 :INTEGER); + (* append formatted string t. Replace the first two % by n1 and n2 *) +VAR j :INTEGER; +BEGIN + j := 0; WHILE (t[j] # 0X) & (t[j] # "%") DO char(t[j]); INC(j) END; + IF t[j] = "%" THEN + int(n1); INC(j); + WHILE (t[j] # 0X) & (t[j] # "%") DO char(t[j]); INC(j) END; + IF t[j] = "%" THEN + int(n2); INC(j); + WHILE t[j] # 0X DO char(t[j]); INC(j) END + END + END +END formatInt2; + +PROCEDURE formatStr* (t, u :ARRAY OF CHAR); + (* append formatted string. Replace the first % in t by u *) +VAR j, k :INTEGER; +BEGIN + j := 0; WHILE (t[j] # 0X) & (t[j] # "%") DO char(t[j]); INC(j) END; + IF t[j] = "%" THEN + k := 0; WHILE u[k] # 0X DO char(u[k]); INC(k) END; + INC(j); WHILE t[j] # 0X DO char(t[j]); INC(j) END + END +END formatStr; + +PROCEDURE hex* (n, width :INTEGER); + (* print width positions of n as hex string. If necessary, prefix with leading zeroes *) + (* note: if n needs more positions than width, the first hex digits are not printed *) +VAR j :INTEGER; + dig :ARRAY 9 OF CHAR; +BEGIN + ASSERT(width > 0); + ASSERT (width <= 8); + dig[width] := 0X; + REPEAT + j := n MOD 16; n := n DIV 16; + IF j < 10 THEN j := ORD("0") + j ELSE j := ORD("A") + j - 10 END; + DEC(width); dig[width] := CHR(j) + UNTIL width = 0; + str (dig); +END hex; + +PROCEDURE flush*; +(* this routine comes at the end. It won't hardly ever be called + because nl also flushes. It is present only in case you + want to write a flushed string which does not end with nl. *) +BEGIN writeChars END flush; + +(* note: global variable 'len' must be 0 on init. Within the core, bodies of imported modules + are not executed, so rely on zero initialisation by Modules.Load *) +END out. + diff --git a/programs/develop/oberon07/Samples/Linux/X11/animation/unix.ob07 b/programs/develop/oberon07/Samples/Linux/X11/animation/unix.ob07 new file mode 100644 index 000000000..d74ed88c1 --- /dev/null +++ b/programs/develop/oberon07/Samples/Linux/X11/animation/unix.ob07 @@ -0,0 +1,74 @@ +MODULE unix; (* connect to unix host *) +IMPORT SYSTEM, _unix; +(* provide some Oberon friendly POSIX without need for SYSTEM *) + +CONST RTLD_LAZY* = 1; + O_RDONLY* = 0; + O_NEWFILE* = 0C2H; (* O_RDWR | O_CREAT | O_EXCL *) + (* O_RDONLY=0, O_WRONLY=1, O_RDWR=2, O_CREAT=0x40, O_EXCL=0x80, O_TRUNC=0x200 *) + FD_SETSIZE* = 1024; (* fd for select() must be smaller than FD_SETSIZE *) + BIT_DEPTH* = _unix.BIT_DEPTH; + LEN_FD_SET = FD_SETSIZE DIV BIT_DEPTH; + +TYPE + timespec* = RECORD + tv_sec*, tv_usec* :INTEGER + END; + fd_set* = POINTER TO RECORD (* for select() *) + bits* :ARRAY LEN_FD_SET OF SET (* 1024 bits *) + END; + +VAR + dlopen* :PROCEDURE [linux] (name, flags :INTEGER) :INTEGER; + dlsym* :PROCEDURE [linux] (p, name :INTEGER) :INTEGER; + dlclose* :PROCEDURE [linux] (p :INTEGER) :INTEGER; + close* :PROCEDURE [linux] (fd :INTEGER) :INTEGER; + exit* :PROCEDURE [linux] (n :INTEGER); + malloc* :PROCEDURE [linux] (sz :INTEGER) :INTEGER; + +PROCEDURE open* (path :ARRAY OF CHAR; flag, perm :INTEGER) :INTEGER; +BEGIN RETURN _unix._open (SYSTEM.ADR(path[0]), flag, perm) END open; + +PROCEDURE read* (fd :INTEGER; VAR buf :ARRAY OF BYTE; len :INTEGER) :INTEGER; +BEGIN RETURN _unix._read (fd, SYSTEM.ADR(buf[0]), len) END read; + +PROCEDURE readByte* (fd :INTEGER; VAR n :BYTE) :INTEGER; +BEGIN RETURN _unix._read (fd, SYSTEM.ADR(n), 1) END readByte; + +PROCEDURE write* (fd :INTEGER; buf :ARRAY OF BYTE; len :INTEGER) :INTEGER; +BEGIN RETURN _unix._write (fd, SYSTEM.ADR(buf[0]), len) END write; + +PROCEDURE writeByte* (fd :INTEGER; n :BYTE) :INTEGER; +BEGIN RETURN _unix._write (fd, SYSTEM.ADR(n), 1) END writeByte; + + +PROCEDURE FD_ZERO* (VAR selectSet :fd_set); +VAR i :INTEGER; +BEGIN FOR i := 0 TO LEN_FD_SET-1 DO selectSet.bits[i] := {} END END FD_ZERO; + +PROCEDURE FD_SET* (fd :INTEGER; VAR selectSet :fd_set); (* set fd bit in a select() fd_set *) +BEGIN INCL(selectSet.bits[fd DIV BIT_DEPTH], fd MOD BIT_DEPTH) +END FD_SET; + +PROCEDURE select* (cnt :INTEGER; readfds, writefds, exceptfds :fd_set; timeout :timespec) :INTEGER; +VAR n1, n2, n3 :INTEGER; +BEGIN + n1 := 0; IF readfds # NIL THEN n1 := SYSTEM.ADR (readfds.bits[0]) END; + n2 := 0; IF writefds # NIL THEN n2 := SYSTEM.ADR (writefds.bits[0]) END; + n3 := 0; IF exceptfds # NIL THEN n3 := SYSTEM.ADR (exceptfds.bits[0]) END; +RETURN _unix._select (cnt, n1, n2, n3, SYSTEM.ADR(timeout)) +END select; + + +PROCEDURE finish*; +BEGIN _unix.finish; END finish; + +BEGIN + dlopen := _unix._dlopen; + dlsym := _unix._dlsym; + dlclose := _unix._dlclose; + close := _unix._close; + exit := _unix._exit; + malloc := _unix._malloc; +END unix. + diff --git a/programs/develop/oberon07/Samples/Linux/X11/filler/_unix.ob07 b/programs/develop/oberon07/Samples/Linux/X11/filler/_unix.ob07 new file mode 100644 index 000000000..0cd77749e --- /dev/null +++ b/programs/develop/oberon07/Samples/Linux/X11/filler/_unix.ob07 @@ -0,0 +1,74 @@ +MODULE _unix; (* connect to unix host *) +IMPORT SYSTEM, API; + +(* how to find C declarations: +- gcc -E preprocess only (to stdout) (preprocessor expand) +- grep -r name /usr/include/* +- ldd progfile +- objdump -T progfile (-t) (-x) +*) + +CONST RTLD_LAZY = 1; + BIT_DEPTH* = API.BIT_DEPTH; + +VAR sym, libc, libdl :INTEGER; + + _dlopen* :PROCEDURE [linux] (name, flags :INTEGER) :INTEGER; + _dlsym* :PROCEDURE [linux] (p, name :INTEGER) :INTEGER; + _dlclose* :PROCEDURE [linux] (p :INTEGER) :INTEGER; + _open* :PROCEDURE [linux] (name, flags, mode :INTEGER) :INTEGER; + _close* :PROCEDURE [linux] (fd :INTEGER) :INTEGER; + _read* :PROCEDURE [linux] (fd, buf, sz :INTEGER): INTEGER; + _write* :PROCEDURE [linux] (fd, buf, sz :INTEGER) :INTEGER; + _exit* :PROCEDURE [linux] (n :INTEGER); + _malloc* :PROCEDURE [linux] (sz :INTEGER) :INTEGER; + _select* :PROCEDURE [linux] (cnt, readfds, writefds, exceptfds, timeout :INTEGER) :INTEGER; + + (* error message to stderr *) +PROCEDURE writeChar (c :CHAR); +VAR ri :INTEGER; +BEGIN ri := _write (2, SYSTEM.ADR(c), 1); ASSERT (ri = 1) END writeChar; + +PROCEDURE writeString (s :ARRAY OF CHAR); +VAR i :INTEGER; +BEGIN i := 0; WHILE s[i] # 0X DO writeChar (s[i]); INC(i) END; END writeString; + +PROCEDURE nl; +BEGIN writeChar (0AX) END nl; + + +PROCEDURE getSymAdr (lib :INTEGER; name :ARRAY OF CHAR; adr :INTEGER); +BEGIN + sym := _dlsym (lib, SYSTEM.ADR(name[0])); + IF sym = 0 THEN writeString ("error: dlsym: "); writeString (name); nl END; + ASSERT (sym # 0); + SYSTEM.PUT (adr, sym) +END getSymAdr; + + +PROCEDURE finish*; +VAR ri :INTEGER; +BEGIN + IF libc # 0 THEN ri := _dlclose (libc); libc := 0 END; + IF libdl # 0 THEN ri := _dlclose (libdl); libdl := 0 END; +END finish; + + +BEGIN + _dlopen := API.dlopen; + _dlsym := API.dlsym; + libc := _dlopen (SYSTEM.SADR("libc.so.6"), RTLD_LAZY); ASSERT (libc # 0); + (* getSymAdr is not used for write() to get writeString() error message going *); + sym := _dlsym (libc, SYSTEM.SADR("write")); ASSERT (sym # 0); SYSTEM.PUT (SYSTEM.ADR(_write), sym); + + libdl := _dlopen (SYSTEM.SADR("libdl.so.2"), RTLD_LAZY); ASSERT (libdl # 0); + getSymAdr (libdl, "dlclose", SYSTEM.ADR(_dlclose)); + + getSymAdr (libc, "open", SYSTEM.ADR(_open)); + getSymAdr (libc, "close", SYSTEM.ADR(_close)); + getSymAdr (libc, "read", SYSTEM.ADR(_read)); + getSymAdr (libc, "exit", SYSTEM.ADR(_exit)); + getSymAdr (libc, "malloc", SYSTEM.ADR(_malloc)); + getSymAdr (libc, "select", SYSTEM.ADR(_select)); +END _unix. + diff --git a/programs/develop/oberon07/Samples/Linux/X11/filler/filler.ob07 b/programs/develop/oberon07/Samples/Linux/X11/filler/filler.ob07 new file mode 100644 index 000000000..969cab918 --- /dev/null +++ b/programs/develop/oberon07/Samples/Linux/X11/filler/filler.ob07 @@ -0,0 +1,221 @@ +MODULE filler; (* filler game, color more fields than the opponent *) +IMPORT SYSTEM, out, unix, gr; + +CONST + Side = 14; (* nr of pixels of a field side *) + width = 62; height = 48; (* board size *) + nrFields = width * height; + BackGroundColor = 0B0B050H; + +VAR fdRandom :INTEGER; (* /dev/urandom *) + base, stride, screenBufSize :INTEGER; + palette :ARRAY 6 OF INTEGER; + field :ARRAY nrFields OF INTEGER; (* color 0..5 *) + visit :ARRAY nrFields OF INTEGER; (* 0 unvisited, 1 neighbour to do, 2 done *) + Acount, Acolor, Bcount, Bcolor :INTEGER; (* player conquered fields and current color *) + rndSeed, rndIndex :INTEGER; + +PROCEDURE check (b :BOOLEAN; n :INTEGER); +BEGIN + IF ~b THEN + out.formatInt ("internal check failed: filler.mod: %", n); out.nl; + out.exit(1) + END +END check; + +PROCEDURE random6 () :INTEGER; (* return random 0..5 *) +VAR n :INTEGER; + b :BYTE; +BEGIN + IF rndIndex = 3 THEN + (* 6 ^ 3 = 216 so 3 random6 nrs fit in one random byte, don't waste entropy *) + n := unix.readByte (fdRandom, b); ASSERT (n = 1); + rndSeed := b; rndIndex := 0; + END; + n := rndSeed MOD 6; rndSeed := rndSeed DIV 6; INC (rndIndex) +RETURN n +END random6; + +PROCEDURE drawRect (x, y, color :INTEGER); +VAR p, i, j :INTEGER; +BEGIN + p := (y*stride + x*4)*Side; + check (p + (Side-1)*stride + (Side-1)*4 <= screenBufSize, 20); + p := base + p; + FOR j := 0 TO Side-1 DO + FOR i := 0 TO Side-1 DO SYSTEM.PUT32 (p, color); INC(p, 4) END; + p := p + stride - Side*4; + END; +END drawRect; + +PROCEDURE clearVisit; +VAR i :INTEGER; +BEGIN FOR i := 0 TO nrFields-1 DO visit[i] := 0 END; END clearVisit; + +PROCEDURE doNeighbour (i, old, new, v :INTEGER; VAR changed :BOOLEAN); + (* helper routine for connect() *) +BEGIN + IF visit[i] = 0 THEN + IF (v = 1) & (field[i] = old) THEN visit[i] := 1; changed := TRUE END; + IF field[i] = new THEN visit[i] := 2; changed := TRUE END + END +END doNeighbour; +(* + all visit := 0; count := 0; visit[corner] := 1 + repeat + changed := false; + foreach: + if (visit = 1) or (visit = 2) then + curVisit = visit + color := new; visit := 3; count++ + foreach neighbour: + if visit = 0 then + if curVisit = 1 then + if color = old then visit := 1; changed := true + if color = new then visit := 2; changed := true + if curVisit = 2 then + if color = new then visit := 2; changed := true + until no changes +*) +PROCEDURE connect (old, new :INTEGER) :INTEGER; +VAR count, i, x, y, v :INTEGER; + changed :BOOLEAN; +BEGIN +out.formatInt2 ("connect: old new % % ", old+1, new+1); + count := 0; + REPEAT + changed := FALSE; + FOR i := 0 TO nrFields-1 DO + v := visit[i]; + IF (v=1) OR (v=2) THEN + field[i] := new; visit[i] := 3; INC(count); + x := i MOD width; y := i DIV width; + IF x > 0 THEN doNeighbour (i-1, old, new, v, changed) END; + IF x < width-1 THEN doNeighbour (i+1, old, new, v, changed) END; + IF y > 0 THEN doNeighbour (i-width, old, new, v, changed) END; + IF y < height-1 THEN doNeighbour (i+width, old, new, v, changed) END; + END + END + UNTIL ~changed +RETURN count +END connect; + +PROCEDURE doMaxGainNeighbour (i, old, new, v :INTEGER; VAR changed :BOOLEAN); + (* helper routine for maxGain() *) +BEGIN + IF visit[i] = 0 THEN + IF v = 1 THEN + IF field[i] = old THEN visit[i] := 1 ELSE visit[i] := 2 END; + changed := TRUE + ELSE + IF field[i] = new THEN visit[i] := 2; changed := TRUE END + END + END +END doMaxGainNeighbour; +(* v=1 & field=old -> visit := 1 + v=1 & field # old -> visit := 2 + v=2 & field = new -> visit := 2 +*) + +PROCEDURE maxGain (old :INTEGER) :INTEGER; + (* return the color which will conquer the most fields *) +VAR + i, x, y, new, v :INTEGER; + max :ARRAY 6 OF INTEGER; + changed :BOOLEAN; +BEGIN + FOR i := 0 TO 5 DO max[i] := 0 END; + REPEAT + changed := FALSE; + FOR i := 0 TO nrFields-1 DO + v := visit[i]; + IF (v=1) OR (v=2) THEN + visit[i] := 3; new := field[i]; INC (max[new]); + x := i MOD width; y := i DIV width; + IF x > 0 THEN doMaxGainNeighbour (i-1, old, new, v, changed) END; + IF x < width-1 THEN doMaxGainNeighbour (i+1, old, new, v, changed) END; + IF y > 0 THEN doMaxGainNeighbour (i-width, old, new, v, changed) END; + IF y < height-1 THEN doMaxGainNeighbour (i+width, old, new, v, changed) END; + END + END + UNTIL ~changed; + x := -1; y := -1; max[Acolor] := -1; max[Bcolor] := -1; +out.str ("maxGain"); out.nl; +FOR i := 0 TO 5 DO out.formatInt2 (" % %", i+1, max[i]); out.nl END; + FOR i := 0 TO 5 DO IF (max[i] > y) & (i # old) THEN x := i; y := max[i] END END +RETURN x +END maxGain; + +PROCEDURE drawAll; +VAR x, y :INTEGER; +BEGIN + gr.screenBegin; + gr.clear (BackGroundColor); + FOR y := 0 TO 5 DO drawRect (0, 6 + y DIV 3 + 2*y, palette[y]) END; + FOR y := 0 TO 47 DO + FOR x := 0 TO 61 DO drawRect (x+2, y, palette[ field[y*width + x] ]) END + END; + gr.screenEnd; +END drawAll; + +PROCEDURE run*; +VAR stop :BOOLEAN; + ev :gr.EventPars; + x, y, i, old :INTEGER; + ch :CHAR; +BEGIN + FOR i := 0 TO nrFields-1 DO field[i] := random6() END; + Acolor := field[47*width]; field[47*width+1] := Acolor; field[46*width] := Acolor; field[46*width+1] := Acolor; + Bcolor := field[width-1]; field[width-2] := Bcolor; field[2*width-2] := Bcolor; field[2*width-1] := Bcolor; + base := gr.base; stride := gr.stride; + gr.createWindow (1000, 700); + screenBufSize := gr.winHeight * stride; + stop := FALSE; + drawAll; + REPEAT + gr.nextEvent (0, ev); + IF ev[0] = gr.EventKeyPressed THEN + (* o.formatInt("key pressed %",ev[2]);o.nl; *) + (* ev[2]: q=24, ESC=9, CR=36 *) + ch := CHR (ev[4]); + IF ev[2] = 9 THEN stop := TRUE END; (* ESC *) + (* IF ch = "q" THEN stop := TRUE END; *) + IF (ch >= "1") & (ch <= "6") THEN + i := ev[4] - ORD("1"); + IF (i # Acolor) & (i # Bcolor) THEN + (* player A *) + old := Acolor; Acolor := i; +out.formatInt ("play color %", Acolor+1); out.nl; + clearVisit; visit[47*width] := 1; + Acount := connect (old, Acolor) +;out.formatInt ("count A = %", Acount); out.nl; out.nl; + (* player B *) + clearVisit; visit[width-1] := 1; old := field[width-1]; + Bcolor := maxGain (old); + clearVisit; visit[width-1] := 1; + Bcount := connect (old, Bcolor); +out.formatInt ("count B = %", Bcount); out.nl; out.nl; + drawAll; + END + END; + ELSIF ev[0] = gr.EventButtonPressed THEN + x := ev[2] DIV Side; y := ev[3] DIV Side; + END; + UNTIL stop; + gr.finish; + unix.finish; +END run; + +BEGIN + fdRandom := unix.open ("/dev/urandom", unix.O_RDONLY, 0); ASSERT (fdRandom # -1); + rndIndex := 3; + (* a partial copy of the lexaloffle pico-8 16-color palette *) + palette[0] := 0FF004DH; (* red *) + palette[1] := 0FFA300H; (* orange *) + palette[2] := 07E2553H; (* dark purple *) + palette[3] := 0008751H; (* dark green *) + palette[4] := 029ADFFH; (* blue *) + palette[5] := 0FF77A8H; (* pink *) + run; +END filler. + diff --git a/programs/develop/oberon07/Samples/Linux/X11/filler/filler.txt b/programs/develop/oberon07/Samples/Linux/X11/filler/filler.txt new file mode 100644 index 000000000..143a343e4 --- /dev/null +++ b/programs/develop/oberon07/Samples/Linux/X11/filler/filler.txt @@ -0,0 +1,15 @@ + +Filler game + +Player and computer each try to conquer the most fields. +Player starts at left bottom and computer at right top. + +At each turn, a new color is chosen and area extended. + +Press 1 .. 6 to choose color. At the left side of the board the top +color has nr 1 and the bottom color nr 6. The current colors of player +and opponent can not be chosen. The current area receives the new color +and is extended with all bordering areas of the chosen color. + +Have fun! + diff --git a/programs/develop/oberon07/Samples/Linux/X11/filler/gr.ob07 b/programs/develop/oberon07/Samples/Linux/X11/filler/gr.ob07 new file mode 100644 index 000000000..c22e75e82 --- /dev/null +++ b/programs/develop/oberon07/Samples/Linux/X11/filler/gr.ob07 @@ -0,0 +1,292 @@ +MODULE gr; (* connect to libX11 *) +IMPORT SYSTEM, unix, out; + +(* +X11 documentation in: +- http://tronche.com/gui/x/xlib/ an X11 reference +- http://www.sbin.org/doc/Xlib an X11 tutorial (this domain has disappeared) +*) + +CONST + InputOutput = 1; + StructureNotifyMask = 20000H; (* input event mask *) + ExposureMask = 8000H; KeyPressMask = 1; KeyReleaseMask = 2; + ButtonPressMask = 4; ButtonReleaseMask = 8; (* PointerNotionMask *) + ZPixmap = 2; + Expose = 12; (* X event type *) ConfigureNotify = 22; KeyPress = 2; ButtonPress = 4; + + EventTimeOut* = 80; (* 0, 0, 0, 0 *) + EventResize* = 81; (* 0, w, h, 0 *) + EventKeyPressed* = 82; (* isPrintable, keyCode (X11 scan code), state, keySym (ASCII) *) + EventKeyReleased* = 83; (* 0, keyCode, state, 0 *) + EventButtonPressed* = 84; (* button, x, y, state *) + EventButtonReleased* = 85; (* button, x, y, state *) + (* mouse button 1-5 = Left, Middle, Right, Scroll wheel up, Scroll wheel down *) + + bit64 = ORD(unix.BIT_DEPTH = 64); + +TYPE EventPars* = ARRAY 5 OF INTEGER; + XEvent = RECORD + val :ARRAY 192 OF BYTE (* union { ..., long pad[24]; } *) + (* val :ARRAY 48 OF CARD32; *) + END; + +VAR ScreenWidth*, ScreenHeight* :INTEGER; + winWidth*, winHeight* :INTEGER; (* draw by writing to pixel buffer: *) + base*, stride* :INTEGER; (* width, height, base ptr, stride in bytes, 32-bit RGB *) + painting :BOOLEAN; + + libX11 :INTEGER; (* handle to dynamic library *) + XOpenDisplay :PROCEDURE [linux] (name :INTEGER) :INTEGER; + XCloseDisplay :PROCEDURE [linux] (display :INTEGER); + XSynchronize :PROCEDURE [linux] (display, onoff :INTEGER) :INTEGER; (* return prev onoff *) + XConnectionNumber :PROCEDURE [linux] (display :INTEGER) :INTEGER; + XCreateWindow :PROCEDURE [linux] (display, parent_window, x, y, w, h, border_width, depth, + class, visual, valuemask, attributes :INTEGER) :INTEGER; (* Window *) + XDefaultScreen :PROCEDURE [linux] (display :INTEGER) :INTEGER; + XDefaultGC :PROCEDURE [linux] (display, screenNr :INTEGER) :INTEGER; (* GC *) + XDisplayWidth :PROCEDURE [linux] (display, screenNr :INTEGER) :INTEGER; + XDisplayHeight :PROCEDURE [linux] (display, screenNr :INTEGER) :INTEGER; + XDefaultVisual :PROCEDURE [linux] (display, screenNr :INTEGER) :INTEGER; (* visual *) + XDefaultRootWindow :PROCEDURE [linux] (display :INTEGER) :INTEGER; (* Window *) + XDefaultDepth :PROCEDURE [linux] (display, screenNr :INTEGER) :INTEGER; + XSelectInput :PROCEDURE [linux] (display, window, event_mask :INTEGER); + XMapWindow :PROCEDURE [linux] (display, window :INTEGER); + XNextEvent :PROCEDURE [linux] (display, XEvent_p :INTEGER); + XPending :PROCEDURE [linux] (display :INTEGER) :INTEGER; + XLookupString :PROCEDURE [linux] (key_event, buffer_return, buflen, keysym_return, status_in_out :INTEGER) :INTEGER; + XCreateImage :PROCEDURE [linux] (display, visual, depth, format, offset, data, + width, height, bitmap_pad, bytes_per_line :INTEGER) :INTEGER; (* ptr to XImage *) + XPutImage :PROCEDURE [linux] (display, window, gc, image, sx, sy, dx, dy, w, h :INTEGER); + + display, screen, window, gc, img :INTEGER; + connectionNr :INTEGER; (* fd of X11 socket *) + readX11 :unix.fd_set; (* used by select() timeout on X11 socket *) + + +PROCEDURE getSymAdr (lib :INTEGER; name :ARRAY OF CHAR; adr :INTEGER); +VAR sym :INTEGER; +BEGIN + sym := unix.dlsym (lib, SYSTEM.ADR(name[0])); + IF sym = 0 THEN out.formatStr ("error: dlsym: %", name); out.nl END; + ASSERT (sym # 0); + SYSTEM.PUT (adr, sym) +END getSymAdr; + + +PROCEDURE init; +BEGIN + display := XOpenDisplay (0); + IF display = 0 THEN out.str ("error: can not open X11 display."); out.nl; out.exit(1) END; + (* ri := XSynchronize (display, 1); *) + connectionNr := XConnectionNumber (display); ASSERT (connectionNr < unix.FD_SETSIZE); + NEW (readX11); unix.FD_ZERO(readX11); unix.FD_SET (connectionNr, readX11); + screen := XDefaultScreen (display); gc := XDefaultGC (display, screen); + ScreenWidth := XDisplayWidth (display, screen); ScreenHeight := XDisplayHeight (display, screen); + base := unix.malloc (ScreenWidth * ScreenHeight * 4); + IF base = 0 THEN + out.formatInt2 ("error: can not allocate screen buffer % x %", ScreenWidth, ScreenHeight); out.nl; out.exit(1); + END; + stride := ScreenWidth * 4; + img := XCreateImage (display, XDefaultVisual (display, screen), XDefaultDepth (display, screen), + ZPixmap, 0, base, ScreenWidth, ScreenHeight, 32, 0); +END init; + + +PROCEDURE finish*; +VAR ri :INTEGER; +BEGIN + IF display # 0 THEN XCloseDisplay(display); display := 0 END; + IF libX11 # 0 THEN ri := unix.dlclose (libX11); libX11 := 0 END; +END finish; + + +PROCEDURE createWindow* (w, h :INTEGER); +VAR eventMask :INTEGER; +BEGIN + IF (w > ScreenWidth) OR (h > ScreenHeight) THEN + out.str ("error: X11.createWindow: window too large"); out.exit(1); + END; + ASSERT ((w >= 0) & (h >= 0)); + window := XCreateWindow (display, XDefaultRootWindow (display), 0, 0, w, h, 0, + XDefaultDepth (display, screen), InputOutput, XDefaultVisual (display, screen), 0, 0); + winWidth := w; winHeight := h; + eventMask := StructureNotifyMask + ExposureMask + KeyPressMask + ButtonPressMask; + XSelectInput (display, window, eventMask); + XMapWindow (display, window); +END createWindow; + + +PROCEDURE screenBegin*; + (* intended to enable future cooperation with iOS / MacOS *) +BEGIN + ASSERT (~painting); painting := TRUE +END screenBegin; + + +PROCEDURE screenEnd*; +BEGIN + ASSERT (painting); + XPutImage (display, window, gc, img, 0, 0, 0, 0, winWidth, winHeight); + painting := FALSE; +END screenEnd; + + +PROCEDURE readInt (e :XEvent; i :INTEGER) :INTEGER; + (* treat XEvent byte array as int array *) +VAR n :INTEGER; +BEGIN + ASSERT (i >= 0); + ASSERT (i < 48); + i := i * 4; + n := e.val[i+3]*1000000H + e.val[i+2]*10000H + e.val[i+1]*100H + e.val[i]; +RETURN n +END readInt; + + +PROCEDURE nextEvent* (msTimeOut :INTEGER; VAR ev :EventPars); +VAR _type, n, ri :INTEGER; + event :XEvent; + x, y, w, h :INTEGER; + timeout :unix.timespec; +BEGIN +(* struct XEvent (64-bit): +any: 4 type 8 serial 4 send_event 8 display 8 window 8 window +expose: 40 any 4 x, y, w, h, count +xconfigure: 48 any 4 x, y, w, h +xkey / xbutton / xmotion: 48 any 8 sub_window 8 time_ms 4 x, y, x_root, y_root 4 state 4 keycode/button +*) +(* struct XEvent (32-bit): +any: 4 type 4 serial 4 send_event 4 display 4 window +expose: 20 any 4 x, y, w, h, count +xconfigure: 24 any 4 x, y, w, h +xkey / xbutton / xmotion: 24 any 4 sub_window 4 time_ms 4 x, y, x_root, y_root 4 state 4 keycode/button +*) + _type := 0; + WHILE _type = 0 DO + IF (msTimeOut > 0) & (XPending(display) = 0) THEN + timeout.tv_sec := msTimeOut DIV 1000; timeout.tv_usec := (msTimeOut MOD 1000) * 1000; + ri := unix.select (connectionNr + 1, readX11, NIL, NIL, timeout); ASSERT (ri # -1); + IF ri = 0 THEN _type := EventTimeOut; ev[1] := 0; ev[2] := 0; ev[3] := 0; ev[4] := 0 END; + END; + IF _type = 0 THEN + XNextEvent (display, SYSTEM.ADR(event)); + CASE readInt (event, 0) OF + Expose : + x := readInt (event, 5 + 5 * bit64); y := readInt (event, 6 + 5 * bit64); + w := readInt (event, 7 + 5 * bit64); h := readInt (event, 8 + 5 * bit64); + XPutImage (display, window, gc, img, x, y, x, y, w, h); + | ConfigureNotify : + w := readInt (event, 8 + 6 * bit64); h := readInt (event, 9 + 6 * bit64); + IF (w # winWidth) & (h # winHeight) THEN + ASSERT ((w >= 0) & (h >= 0)); + IF w > ScreenWidth THEN w := ScreenWidth END; + IF h > ScreenHeight THEN h := ScreenHeight END; + winWidth := w; winHeight := h; + ev[0] := EventResize; ev[1] := 0; ev[2] := w; ev[3] := h; ev[4] := 0; + END; + | KeyPress : + _type := EventKeyPressed; + x := XLookupString (SYSTEM.ADR(event), 0, 0, SYSTEM.ADR(n), 0); (* KeySym *) + IF (n = 8) OR (n = 10) OR (n >= 32) & (n <= 126) THEN ev[1] := 1 ELSE ev[1] := 0; n := 0 END; (* isprint *) + ev[2] := readInt (event, 13 + 8 * bit64); (* keycode *) + ev[3] := readInt (event, 12 + 8 * bit64); (* state *) + ev[4] := n; (* KeySym *) + | ButtonPress : + _type := EventButtonPressed; + ev[1] := readInt (event, 13 + 8 * bit64); (* button *) + ev[2] := readInt (event, 8 + 8 * bit64); (* x *) + ev[3] := readInt (event, 9 + 8 * bit64); (* y *) + ev[4] := readInt (event, 12 + 8 * bit64); (* state *) + ELSE + END + END + END; + ev[0] := _type +END nextEvent; + + +PROCEDURE clear* (color :INTEGER); (* fill window area with color *) +VAR p, i, j :INTEGER; +BEGIN + FOR j := 0 TO winHeight-1 DO + p := base + j*stride; + FOR i := 0 TO winWidth-1 DO SYSTEM.PUT32 (p, color); INC (p, 4) END + END +END clear; + + +(* +PROCEDURE blitError (stride, x, y, w, h :INTEGER); +BEGIN + o.formatInt ("error: screen.blit (src, %)", stride); + o.formatInt2 (", %, %", x, y); + o.formatInt2 (", %, %) out of bounds", w, h); o.nl; + ASSERT (FALSE) +END blitError; + +PROCEDURE blit* (src, srcStride, x, y, w, h :INTEGER); +VAR dstStride, p :INTEGER; +BEGIN + IF (x < 0) OR (y < 0) THEN blitError (srcStride, x, y, w, h) END; + IF (w <= 0) OR (h <= 0) THEN blitError (srcStride, x, y, w, h) END; + IF (x + w > ScreenWidth) OR (y + h > ScreenHeight) THEN blitError (srcStride, x, y, w, h) END; + + dstStride := ScreenWidth - w; + p := ScreenBase + y * ScreenWidth + x * 4; + REPEAT + SYSTEM.COPY (src, p, w); + INC (src, srcStride); INC (p, dstStride); DEC (h) + UNTIL h = 0 +END blit; +*) + +(* +PROCEDURE setPixel* (x, y, color :INTEGER); +VAR p :INTEGER; +BEGIN + ASSERT ((x >= 0) & (x < ScreenWidth) & (y >= 0) & (y < ScreenHeight)); + screenBegin; p := base + (y*ScreenWidth + x)*4; SYSTEM.PUT32 (p, color); p := p + 4 screenEnd +END setPixel; +*) + +(* +PROCEDURE loop; (* example main loop *) +VAR e :EventPars; + stop :BOOLEAN; +BEGIN + createWindow (200, 200); + stop := FALSE; + REPEAT + nextEvent (0, e); + IF e[0] = EventKeyPressed THEN stop := TRUE END; + UNTIL stop; + XCloseDisplay (display); +END loop; +*) + + +BEGIN + libX11 := unix.dlopen (SYSTEM.SADR("libX11.so.6"), unix.RTLD_LAZY); ASSERT (libX11 # 0); + getSymAdr (libX11, "XOpenDisplay", SYSTEM.ADR(XOpenDisplay)); + getSymAdr (libX11, "XCloseDisplay", SYSTEM.ADR(XCloseDisplay)); + getSymAdr (libX11, "XSynchronize", SYSTEM.ADR(XSynchronize)); + getSymAdr (libX11, "XConnectionNumber", SYSTEM.ADR(XConnectionNumber)); + getSymAdr (libX11, "XCreateWindow", SYSTEM.ADR(XCreateWindow)); + getSymAdr (libX11, "XDefaultScreen", SYSTEM.ADR(XDefaultScreen)); + getSymAdr (libX11, "XDefaultGC", SYSTEM.ADR(XDefaultGC)); + getSymAdr (libX11, "XDisplayWidth", SYSTEM.ADR(XDisplayWidth)); + getSymAdr (libX11, "XDisplayHeight", SYSTEM.ADR(XDisplayHeight)); + getSymAdr (libX11, "XDefaultVisual", SYSTEM.ADR(XDefaultVisual)); + getSymAdr (libX11, "XDefaultRootWindow", SYSTEM.ADR(XDefaultRootWindow)); + getSymAdr (libX11, "XDefaultDepth", SYSTEM.ADR(XDefaultDepth)); + getSymAdr (libX11, "XSelectInput", SYSTEM.ADR(XSelectInput)); + getSymAdr (libX11, "XMapWindow", SYSTEM.ADR(XMapWindow)); + getSymAdr (libX11, "XNextEvent", SYSTEM.ADR(XNextEvent)); + getSymAdr (libX11, "XPending", SYSTEM.ADR(XPending)); + getSymAdr (libX11, "XLookupString", SYSTEM.ADR(XLookupString)); + getSymAdr (libX11, "XCreateImage", SYSTEM.ADR(XCreateImage)); + getSymAdr (libX11, "XPutImage", SYSTEM.ADR(XPutImage)); + init; +END gr. + diff --git a/programs/develop/oberon07/Samples/Linux/X11/filler/out.ob07 b/programs/develop/oberon07/Samples/Linux/X11/filler/out.ob07 new file mode 100644 index 000000000..ad8478ce9 --- /dev/null +++ b/programs/develop/oberon07/Samples/Linux/X11/filler/out.ob07 @@ -0,0 +1,142 @@ +MODULE out; (* formatted output to stdout *) +(* Wim Niemann, Jan Tuitman 06-OCT-2016 *) + +IMPORT SYSTEM, _unix; + +(* example: IMPORT o:=out; + o.str("Hello, World!");o.nl; + o.formatInt("n = %", 3);o.nl; +*) + +(* +The output functions buffer the characters in buf. This buffer is flushed when out.nl is +called and also when the buffer is full. + +Calling flush once per line is far more efficient then one system call per +character, but this is noticable only at very long outputs. +*) + +CONST MAX = 63; (* last position in buf *) + +VAR len :INTEGER; (* string length in buf *) + buf :ARRAY MAX+1 OF BYTE; + +PROCEDURE exit* (n :INTEGER); + (* prevent IMPORT unix for many programs *) +BEGIN _unix._exit(n) END exit; + +PROCEDURE writeChars; + (* write buf to the output function and set to empty string *) +VAR ri :INTEGER; +BEGIN + IF len > 0 THEN + (* buf[len] := 0X; *) + ri := _unix._write (1, SYSTEM.ADR(buf), len); ASSERT (ri = len); (* stdout *) + len := 0 + END +END writeChars; + +PROCEDURE nl*; (* append a newline to buf and flush *) +BEGIN + IF len = MAX THEN writeChars END; + buf[len] := 0AH; INC(len); + (* unix: 0AX; Oberon: 0DX; + Windows: IF len >= MAX-1 THEN 0DX 0AX; *) + writeChars; +END nl; + +PROCEDURE char* (c :CHAR); + (* append char to the end of buf *) +BEGIN + IF len = MAX THEN writeChars END; + buf[len] := ORD(c); INC(len) +END char; + +PROCEDURE str* (t :ARRAY OF CHAR); + (* append t to buf *) +VAR j :INTEGER; +BEGIN + j := 0; WHILE t[j] # 0X DO char(t[j]); INC(j) END +END str; + +PROCEDURE int* (n :INTEGER); + (* append integer; append n to d, return TRUE on overflow of d *) +VAR j :INTEGER; + sign :BOOLEAN; + dig :ARRAY 11 OF CHAR; (* assume 32 bit INTEGER *) +BEGIN + sign := FALSE; IF n < 0 THEN sign := TRUE; n := -n END; + IF n < 0 THEN + str ("-2147483648"); + ELSE + j := 0; + REPEAT dig[j] := CHR (n MOD 10 + 30H); n := n DIV 10; INC(j) UNTIL n = 0; + IF sign THEN char ("-") END; + REPEAT DEC(j); char(dig[j]) UNTIL j = 0; + END +END int; + +PROCEDURE formatInt* (t :ARRAY OF CHAR; n :INTEGER); + (* append formatted string t. Replace the first % by n *) +VAR j :INTEGER; +BEGIN + j := 0; WHILE (t[j] # 0X) & (t[j] # "%") DO char(t[j]); INC(j) END; + IF t[j] = "%" THEN + int(n); INC(j); + WHILE t[j] # 0X DO char(t[j]); INC(j) END + END +END formatInt; + +PROCEDURE formatInt2* (t:ARRAY OF CHAR; n1, n2 :INTEGER); + (* append formatted string t. Replace the first two % by n1 and n2 *) +VAR j :INTEGER; +BEGIN + j := 0; WHILE (t[j] # 0X) & (t[j] # "%") DO char(t[j]); INC(j) END; + IF t[j] = "%" THEN + int(n1); INC(j); + WHILE (t[j] # 0X) & (t[j] # "%") DO char(t[j]); INC(j) END; + IF t[j] = "%" THEN + int(n2); INC(j); + WHILE t[j] # 0X DO char(t[j]); INC(j) END + END + END +END formatInt2; + +PROCEDURE formatStr* (t, u :ARRAY OF CHAR); + (* append formatted string. Replace the first % in t by u *) +VAR j, k :INTEGER; +BEGIN + j := 0; WHILE (t[j] # 0X) & (t[j] # "%") DO char(t[j]); INC(j) END; + IF t[j] = "%" THEN + k := 0; WHILE u[k] # 0X DO char(u[k]); INC(k) END; + INC(j); WHILE t[j] # 0X DO char(t[j]); INC(j) END + END +END formatStr; + +PROCEDURE hex* (n, width :INTEGER); + (* print width positions of n as hex string. If necessary, prefix with leading zeroes *) + (* note: if n needs more positions than width, the first hex digits are not printed *) +VAR j :INTEGER; + dig :ARRAY 9 OF CHAR; +BEGIN + ASSERT(width > 0); + ASSERT (width <= 8); + dig[width] := 0X; + REPEAT + j := n MOD 16; n := n DIV 16; + IF j < 10 THEN j := ORD("0") + j ELSE j := ORD("A") + j - 10 END; + DEC(width); dig[width] := CHR(j) + UNTIL width = 0; + str (dig); +END hex; + +PROCEDURE flush*; +(* this routine comes at the end. It won't hardly ever be called + because nl also flushes. It is present only in case you + want to write a flushed string which does not end with nl. *) +BEGIN writeChars END flush; + +(* note: global variable 'len' must be 0 on init. Within the core, bodies of imported modules + are not executed, so rely on zero initialisation by Modules.Load *) +END out. + diff --git a/programs/develop/oberon07/Samples/Linux/X11/filler/unix.ob07 b/programs/develop/oberon07/Samples/Linux/X11/filler/unix.ob07 new file mode 100644 index 000000000..d74ed88c1 --- /dev/null +++ b/programs/develop/oberon07/Samples/Linux/X11/filler/unix.ob07 @@ -0,0 +1,74 @@ +MODULE unix; (* connect to unix host *) +IMPORT SYSTEM, _unix; +(* provide some Oberon friendly POSIX without need for SYSTEM *) + +CONST RTLD_LAZY* = 1; + O_RDONLY* = 0; + O_NEWFILE* = 0C2H; (* O_RDWR | O_CREAT | O_EXCL *) + (* O_RDONLY=0, O_WRONLY=1, O_RDWR=2, O_CREAT=0x40, O_EXCL=0x80, O_TRUNC=0x200 *) + FD_SETSIZE* = 1024; (* fd for select() must be smaller than FD_SETSIZE *) + BIT_DEPTH* = _unix.BIT_DEPTH; + LEN_FD_SET = FD_SETSIZE DIV BIT_DEPTH; + +TYPE + timespec* = RECORD + tv_sec*, tv_usec* :INTEGER + END; + fd_set* = POINTER TO RECORD (* for select() *) + bits* :ARRAY LEN_FD_SET OF SET (* 1024 bits *) + END; + +VAR + dlopen* :PROCEDURE [linux] (name, flags :INTEGER) :INTEGER; + dlsym* :PROCEDURE [linux] (p, name :INTEGER) :INTEGER; + dlclose* :PROCEDURE [linux] (p :INTEGER) :INTEGER; + close* :PROCEDURE [linux] (fd :INTEGER) :INTEGER; + exit* :PROCEDURE [linux] (n :INTEGER); + malloc* :PROCEDURE [linux] (sz :INTEGER) :INTEGER; + +PROCEDURE open* (path :ARRAY OF CHAR; flag, perm :INTEGER) :INTEGER; +BEGIN RETURN _unix._open (SYSTEM.ADR(path[0]), flag, perm) END open; + +PROCEDURE read* (fd :INTEGER; VAR buf :ARRAY OF BYTE; len :INTEGER) :INTEGER; +BEGIN RETURN _unix._read (fd, SYSTEM.ADR(buf[0]), len) END read; + +PROCEDURE readByte* (fd :INTEGER; VAR n :BYTE) :INTEGER; +BEGIN RETURN _unix._read (fd, SYSTEM.ADR(n), 1) END readByte; + +PROCEDURE write* (fd :INTEGER; buf :ARRAY OF BYTE; len :INTEGER) :INTEGER; +BEGIN RETURN _unix._write (fd, SYSTEM.ADR(buf[0]), len) END write; + +PROCEDURE writeByte* (fd :INTEGER; n :BYTE) :INTEGER; +BEGIN RETURN _unix._write (fd, SYSTEM.ADR(n), 1) END writeByte; + + +PROCEDURE FD_ZERO* (VAR selectSet :fd_set); +VAR i :INTEGER; +BEGIN FOR i := 0 TO LEN_FD_SET-1 DO selectSet.bits[i] := {} END END FD_ZERO; + +PROCEDURE FD_SET* (fd :INTEGER; VAR selectSet :fd_set); (* set fd bit in a select() fd_set *) +BEGIN INCL(selectSet.bits[fd DIV BIT_DEPTH], fd MOD BIT_DEPTH) +END FD_SET; + +PROCEDURE select* (cnt :INTEGER; readfds, writefds, exceptfds :fd_set; timeout :timespec) :INTEGER; +VAR n1, n2, n3 :INTEGER; +BEGIN + n1 := 0; IF readfds # NIL THEN n1 := SYSTEM.ADR (readfds.bits[0]) END; + n2 := 0; IF writefds # NIL THEN n2 := SYSTEM.ADR (writefds.bits[0]) END; + n3 := 0; IF exceptfds # NIL THEN n3 := SYSTEM.ADR (exceptfds.bits[0]) END; +RETURN _unix._select (cnt, n1, n2, n3, SYSTEM.ADR(timeout)) +END select; + + +PROCEDURE finish*; +BEGIN _unix.finish; END finish; + +BEGIN + dlopen := _unix._dlopen; + dlsym := _unix._dlsym; + dlclose := _unix._dlclose; + close := _unix._close; + exit := _unix._exit; + malloc := _unix._malloc; +END unix. + diff --git a/programs/develop/oberon07/Samples/MSP430/Blink.ob07 b/programs/develop/oberon07/Samples/MSP430/Blink.ob07 new file mode 100644 index 000000000..0434b7e21 --- /dev/null +++ b/programs/develop/oberon07/Samples/MSP430/Blink.ob07 @@ -0,0 +1,43 @@ +(* + +Пример для LaunchPad MSP-EXP430G2 Rev1.5 + + Мигает красный светодиод. + +*) +MODULE Blink; + +IMPORT SYSTEM, MSP430; + + +CONST + + REDLED = {0}; + + (* регистры порта P1 *) + P1OUT = 21H; + P1DIR = 22H; + + +PROCEDURE inv_bits (mem: INTEGER; bits: SET); +VAR + b: BYTE; + +BEGIN + SYSTEM.GET(mem, b); + SYSTEM.PUT8(mem, BITS(b) / bits) +END inv_bits; + + +BEGIN + (* инициализация регистра P1DIR *) + SYSTEM.PUT8(P1DIR, REDLED); + + (* бесконечный цикл *) + WHILE TRUE DO + (* изменить состояние светодиода *) + inv_bits(P1OUT, REDLED); + (* задержка *) + MSP430.Delay(800) + END +END Blink. diff --git a/programs/develop/oberon07/Samples/MSP430/Button.ob07 b/programs/develop/oberon07/Samples/MSP430/Button.ob07 new file mode 100644 index 000000000..2470ed4ee --- /dev/null +++ b/programs/develop/oberon07/Samples/MSP430/Button.ob07 @@ -0,0 +1,103 @@ +(* + +Пример для LaunchPad MSP-EXP430G2 Rev1.5 + + Мигает зеленый светодиод. + При нажатии на кнопку P1.3, включается/выключается красный светодиод. + +*) + +MODULE Button; + +IMPORT SYSTEM, MSP430; + + +CONST + + REDLED = {0}; + GREENLED = {6}; + BUTTON = {3}; + + (* регистры порта P1 *) + P1OUT = 21H; + P1DIR = 22H; + P1IFG = 23H; + P1IE = 25H; + P1REN = 27H; + + +PROCEDURE test_bits (mem: INTEGER; bits: SET): SET; +VAR + b: BYTE; + +BEGIN + SYSTEM.GET(mem, b) + RETURN bits * BITS(b) +END test_bits; + + +PROCEDURE set_bits (mem: INTEGER; bits: SET); +VAR + b: BYTE; + +BEGIN + SYSTEM.GET(mem, b); + SYSTEM.PUT8(mem, BITS(b) + bits) +END set_bits; + + +PROCEDURE clr_bits (mem: INTEGER; bits: SET); +VAR + b: BYTE; + +BEGIN + SYSTEM.GET(mem, b); + SYSTEM.PUT8(mem, BITS(b) - bits) +END clr_bits; + + +PROCEDURE inv_bits (mem: INTEGER; bits: SET); +VAR + b: BYTE; + +BEGIN + SYSTEM.GET(mem, b); + SYSTEM.PUT8(mem, BITS(b) / bits) +END inv_bits; + + +(* обработчик прерываний *) +PROCEDURE int (priority: INTEGER; interrupt: MSP430.TInterrupt); +BEGIN + IF priority = 18 THEN (* прерывание от порта P1 *) + IF test_bits(P1IFG, BUTTON) = BUTTON THEN (* нажата кнопка *) + inv_bits(P1OUT, REDLED); (* изменить состояние светодиода *) + MSP430.Delay(500); (* задержка для отпускания кнопки *) + clr_bits(P1IFG, BUTTON) (* сбросить флаг прерывания *) + END + END +END int; + + +PROCEDURE main; +BEGIN + (* инициализация регистров порта P1 *) + SYSTEM.PUT8(P1DIR, REDLED + GREENLED); (* выход *) + set_bits(P1REN, BUTTON); (* включить подтягивающий резистор *) + set_bits(P1OUT, BUTTON); (* подтяжка к питанию *) + set_bits(P1IE, BUTTON); (* разрешить прерывания от кнопки *) + + MSP430.SetIntProc(int); (* назначить обработчик прерываний *) + MSP430.EInt; (* разрешить прерывания *) + + (* бесконечный цикл *) + WHILE TRUE DO + inv_bits(P1OUT, GREENLED); (* изменить состояние светодиода *) + MSP430.Delay(800) (* задержка *) + END +END main; + + +BEGIN + main +END Button. diff --git a/programs/develop/oberon07/Samples/MSP430/Flash.ob07 b/programs/develop/oberon07/Samples/MSP430/Flash.ob07 new file mode 100644 index 000000000..0b4e59bb5 --- /dev/null +++ b/programs/develop/oberon07/Samples/MSP430/Flash.ob07 @@ -0,0 +1,157 @@ +(* + +Пример для LaunchPad MSP-EXP430G2 Rev1.5 + + Запись флэш-памяти. + При успешном завершении, включается зеленый светодиод, + иначе - красный. + +*) + +MODULE Flash; + +IMPORT SYSTEM, MSP430; + + +CONST + + REDLED = {0}; + GREENLED = {6}; + + (* регистры порта P1 *) + P1OUT = 21H; + P1DIR = 22H; + + FERASE = {1}; (* режим "стереть" *) + FWRITE = {6}; (* режим "записать" *) + + +PROCEDURE set_bits (mem: INTEGER; bits: SET); +VAR + b: BYTE; + +BEGIN + SYSTEM.GET(mem, b); + SYSTEM.PUT8(mem, BITS(b) + bits) +END set_bits; + + +PROCEDURE clr_bits (mem: INTEGER; bits: SET); +VAR + b: BYTE; + +BEGIN + SYSTEM.GET(mem, b); + SYSTEM.PUT8(mem, BITS(b) - bits) +END clr_bits; + + +(* + стирание и запись флэш-памяти + adr - адрес + value - значение для записи + mode - режим (стереть/записать) +*) +PROCEDURE Write (adr, value: INTEGER; mode: SET); +CONST + (* сторожевой таймер *) + WDTCTL = 0120H; + WDTHOLD = {7}; + WDTPW = {9, 11, 12, 14}; + + (* регистры контроллера флэш-памяти *) + FCTL1 = 0128H; + ERASE = {1}; + WRT = {6}; + + FCTL2 = 012AH; + FN0 = {0}; + FN1 = {1}; + FN2 = {2}; + FN3 = {3}; + FN4 = {4}; + FN5 = {5}; + FSSEL0 = {6}; + FSSEL1 = {7}; + + FCTL3 = 012CH; + LOCK = {4}; + + FWKEY = {8, 10, 13, 15}; + +VAR + wdt: SET; + +BEGIN + IF (mode = ERASE) OR (mode = WRT) THEN (* проверить заданный режим *) + SYSTEM.GET(WDTCTL, wdt); (* сохранить значение регистра сторожевого таймера *) + SYSTEM.PUT(WDTCTL, WDTPW + WDTHOLD); (* остановить сторожевой таймер *) + SYSTEM.PUT(FCTL2, FWKEY + FSSEL1 + FN0); (* тактовый генератор контроллера флэш-памяти = SMCLK, делитель = 2 *) + SYSTEM.PUT(FCTL3, FWKEY); (* сбросить флаг LOCK *) + SYSTEM.PUT(FCTL1, FWKEY + mode); (* установить режим (записать или стереть) *) + SYSTEM.PUT(adr, value); (* запись *) + SYSTEM.PUT(FCTL1, FWKEY); (* сбросить режим *) + SYSTEM.PUT(FCTL3, FWKEY + LOCK); (* установить LOCK *) + SYSTEM.PUT(WDTCTL, WDTPW + wdt * {0..7}) (* восстановить сторожевой таймер *) + END +END Write; + + +(* обработчик ошибок *) +PROCEDURE trap (modNum, modName, err, line: INTEGER); +BEGIN + set_bits(P1OUT, REDLED) (* включить красный светодиод *) +END trap; + + +PROCEDURE main; +CONST + seg_adr = 0FC00H; (* адрес сегмента для стирания и записи (ДОЛЖЕН БЫТЬ СВОБОДНЫМ!) *) + +VAR + adr, x, i: INTEGER; + + free: RECORD address, size: INTEGER END; + +BEGIN + (* инициализация регистров порта P1 *) + SYSTEM.PUT8(P1DIR, REDLED + GREENLED); (* выход *) + + (* выключить светодиоды *) + clr_bits(P1OUT, REDLED + GREENLED); + + MSP430.SetTrapProc(trap); (* назначить обработчик ошибок *) + + ASSERT(seg_adr MOD 512 = 0); (* адрес сегмента должен быть кратным 512 *) + + MSP430.GetFreeFlash(free.address, free.size); + + (* проверить, свободен ли сегмент *) + ASSERT(free.address <= seg_adr); + ASSERT(seg_adr + 511 <= free.address + free.size); + + Write(seg_adr, 0, FERASE); (* стереть сегмент *) + + (* записать в сегмент числа 0..255 (256 слов) *) + adr := seg_adr; + FOR i := 0 TO 255 DO + Write(adr, i, FWRITE); + INC(adr, 2) + END; + + (* проверить запись *) + adr := seg_adr; + FOR i := 0 TO 255 DO + SYSTEM.GET(adr, x); + ASSERT(x = i); (* если x # i, будет вызван обработчик ошибок *) + INC(adr, 2) + END; + + (* если нет ошибок, включить зеленый светодиод *) + set_bits(P1OUT, GREENLED) +END main; + + +BEGIN + main +END Flash. diff --git a/programs/develop/oberon07/Samples/MSP430/Restart.ob07 b/programs/develop/oberon07/Samples/MSP430/Restart.ob07 new file mode 100644 index 000000000..1f3f4c66a --- /dev/null +++ b/programs/develop/oberon07/Samples/MSP430/Restart.ob07 @@ -0,0 +1,106 @@ +(* + +Пример для LaunchPad MSP-EXP430G2 Rev1.5 + + При нажатии на кнопку P1.3, инкрементируется + переменная-счетчик перезапусков и программа + перезапускается. + В зависимости от четности счетчика перезапусков, + включается зеленый или красный светодиод. + +*) + +MODULE Restart; + +IMPORT SYSTEM, MSP430; + + +CONST + + REDLED = {0}; + GREENLED = {6}; + BUTTON = {3}; + + (* регистры порта P1 *) + P1OUT = 21H; + P1DIR = 22H; + P1IFG = 23H; + P1IE = 25H; + P1REN = 27H; + + +VAR + + count: INTEGER; (* счетчик перезапусков *) + + +PROCEDURE set_bits (mem: INTEGER; bits: SET); +VAR + b: BYTE; + +BEGIN + SYSTEM.GET(mem, b); + SYSTEM.PUT8(mem, BITS(b) + bits) +END set_bits; + + +PROCEDURE clr_bits (mem: INTEGER; bits: SET); +VAR + b: BYTE; + +BEGIN + SYSTEM.GET(mem, b); + SYSTEM.PUT8(mem, BITS(b) - bits) +END clr_bits; + + +PROCEDURE test_bits (mem: INTEGER; bits: SET): SET; +VAR + b: BYTE; + +BEGIN + SYSTEM.GET(mem, b) + RETURN bits * BITS(b) +END test_bits; + + +(* обработчик прерываний *) +PROCEDURE int (priority: INTEGER; interrupt: MSP430.TInterrupt); +BEGIN + IF priority = 18 THEN (* прерывание от порта P1 *) + IF test_bits(P1IFG, BUTTON) = BUTTON THEN (* нажата кнопка *) + INC(count); (* увеличить счетчик *) + MSP430.Delay(500); (* задержка для отпускания кнопки *) + clr_bits(P1IFG, BUTTON); (* сбросить флаг прерывания *) + MSP430.Restart (* перезапустить программу *) + END + END +END int; + + +PROCEDURE main; +BEGIN + (* инициализация регистров порта P1 *) + SYSTEM.PUT8(P1DIR, REDLED + GREENLED); (* выход *) + set_bits(P1REN, BUTTON); (* включить подтягивающий резистор *) + set_bits(P1OUT, BUTTON); (* подтяжка к питанию *) + set_bits(P1IE, BUTTON); (* разрешить прерывания от кнопки *) + + (* выключить светодиоды *) + clr_bits(P1OUT, REDLED + GREENLED); + + MSP430.SetIntProc(int); (* назначить обработчик прерываний *) + MSP430.EInt; (* разрешить прерывания *) + + IF ODD(count) THEN + set_bits(P1OUT, GREENLED) (* нечетное - вкл. зеленый *) + ELSE + set_bits(P1OUT, REDLED) (* четное - вкл. красный *) + END + +END main; + + +BEGIN + main +END Restart. diff --git a/programs/develop/oberon07/Samples/MSP430/TimerA.ob07 b/programs/develop/oberon07/Samples/MSP430/TimerA.ob07 new file mode 100644 index 000000000..e92090878 --- /dev/null +++ b/programs/develop/oberon07/Samples/MSP430/TimerA.ob07 @@ -0,0 +1,118 @@ +(* + +Пример для LaunchPad MSP-EXP430G2 Rev1.5 + + Светодиоды мигают по сигналам от таймера A + +*) + +MODULE TimerA; + +IMPORT SYSTEM, MSP430; + + +CONST + + REDLED = {0}; + GREENLED = {6}; + + (* регистры порта P1 *) + P1OUT = 21H; + P1DIR = 22H; + + + (* регистры таймера A *) + TACTL = 0160H; + + (* биты регистра TACTL *) + TAIFG = {0}; + TAIE = {1}; + TACLR = {2}; + MC0 = {4}; + MC1 = {5}; + ID0 = {6}; + ID1 = {7}; + TASSEL0 = {8}; + TASSEL1 = {9}; + + TAR = 0170H; + + TACCTL0 = 0162H; + + (* биты регистра TACCTL0 *) + CCIE = {4}; + CAP = {8}; + + TACCR0 = 0172H; + + +PROCEDURE set_bits (mem: INTEGER; bits: SET); +VAR + b: BYTE; + +BEGIN + SYSTEM.GET(mem, b); + SYSTEM.PUT8(mem, BITS(b) + bits) +END set_bits; + + +PROCEDURE clr_bits (mem: INTEGER; bits: SET); +VAR + b: BYTE; + +BEGIN + SYSTEM.GET(mem, b); + SYSTEM.PUT8(mem, BITS(b) - bits) +END clr_bits; + + +PROCEDURE inv_bits (mem: INTEGER; bits: SET); +VAR + b: BYTE; + +BEGIN + SYSTEM.GET(mem, b); + SYSTEM.PUT8(mem, BITS(b) / bits) +END inv_bits; + + +(* обработчик прерываний *) +PROCEDURE int (priority: INTEGER; interrupt: MSP430.TInterrupt); +VAR + x: SET; + +BEGIN + IF priority = 24 THEN (* прерывание от таймера A *) + SYSTEM.GET(TACTL, x); (* взять регистр TACTL *) + IF TAIFG * x = TAIFG THEN (* прерывание было *) + inv_bits(P1OUT, REDLED); (* изменить состояние светодиода *) + inv_bits(P1OUT, GREENLED); (* изменить состояние светодиода *) + SYSTEM.PUT(TACTL, x - TAIFG) (* сбросить флаг прерывания и обновить регистр TACTL *) + END + END +END int; + + +PROCEDURE main; +BEGIN + (* инициализация регистра P1DIR *) + SYSTEM.PUT8(P1DIR, REDLED + GREENLED); + + (* начальное состояние светодиодов *) + set_bits(P1OUT, GREENLED); (* включен *) + clr_bits(P1OUT, REDLED); (* выключен *) + + MSP430.SetIntProc(int); (* назначить обработчик прерываний *) + MSP430.EInt; (* разрешить прерывания *) + + (* инициализация регистров таймера A *) + SYSTEM.PUT(TAR, 0); + SYSTEM.PUT(TACCTL0, CCIE + CAP); + SYSTEM.PUT(TACCR0, 1000); + SYSTEM.PUT(TACTL, TAIE + MC0 + TASSEL0) +END main; + + +BEGIN + main +END TimerA. diff --git a/programs/develop/oberon07/Samples/MSP430/TwoTimers.ob07 b/programs/develop/oberon07/Samples/MSP430/TwoTimers.ob07 new file mode 100644 index 000000000..5dfcad16c --- /dev/null +++ b/programs/develop/oberon07/Samples/MSP430/TwoTimers.ob07 @@ -0,0 +1,143 @@ +(* + +Пример для LaunchPad MSP-EXP430G2 Rev1.5 + + Зеленый светодиод мигает по сигналам от таймера A, + красный - по сигналам от сторожевого таймера в интервальном режиме + +*) + +MODULE TwoTimers; + +IMPORT SYSTEM, MSP430; + + +CONST + + REDLED = {0}; + GREENLED = {6}; + + (* регистры порта P1 *) + P1OUT = 21H; + P1DIR = 22H; + + + (* регистр разрешения прерываний 1 *) + IE1 = 00H; + + (* биты регистра IE1 *) + WDTIE = {0}; + NMIIE = {4}; + + + (* регистр флагов прерываний 1 *) + IFG1 = 02H; + + (* биты регистра IFG1 *) + WDTIFG = {0}; + NMIIFG = {4}; + + + WDTCTL = 0120H; (* регистр сторожевого таймера *) + + (* биты регистра WDTCTL *) + WDTIS0 = {0}; + WDTIS1 = {1}; + WDTSSEL = {2}; + WDTCNTCL = {3}; + WDTTMSEL = {4}; + WDTNMI = {5}; + WDTNMIES = {6}; + WDTHOLD = {7}; + WDTPW = {9, 11, 12, 14}; (* ключ защиты *) + + + (* регистры таймера A *) + TACTL = 0160H; + + (* биты регистра TACTL *) + TAIFG = {0}; + TAIE = {1}; + TACLR = {2}; + MC0 = {4}; + MC1 = {5}; + ID0 = {6}; + ID1 = {7}; + TASSEL0 = {8}; + TASSEL1 = {9}; + + TAR = 0170H; + + TACCTL0 = 0162H; + + (* биты регистра TACCTL0 *) + CCIE = {4}; + CAP = {8}; + + TACCR0 = 0172H; + + +PROCEDURE set_bits (mem: INTEGER; bits: SET); +VAR + b: BYTE; + +BEGIN + SYSTEM.GET(mem, b); + SYSTEM.PUT8(mem, BITS(b) + bits) +END set_bits; + + +PROCEDURE inv_bits (mem: INTEGER; bits: SET); +VAR + b: BYTE; + +BEGIN + SYSTEM.GET(mem, b); + SYSTEM.PUT8(mem, BITS(b) / bits) +END inv_bits; + + +(* обработчик прерываний *) +PROCEDURE int (priority: INTEGER; interrupt: MSP430.TInterrupt); +VAR + x: SET; + +BEGIN + IF priority = 26 THEN (* прерывание от сторожевого таймера *) + inv_bits(P1OUT, REDLED) (* изменить состояние светодиода *) + ELSIF priority = 24 THEN (* прерывание от таймера A *) + SYSTEM.GET(TACTL, x); (* взять регистр TACTL *) + IF TAIFG * x = TAIFG THEN (* прерывание было *) + inv_bits(P1OUT, GREENLED); (* изменить состояние светодиода *) + SYSTEM.PUT(TACTL, x - TAIFG) (* сбросить флаг прерывания и обновить регистр TACTL *) + END + END +END int; + + +PROCEDURE main; +BEGIN + (* инициализация регистра P1DIR *) + set_bits(P1DIR, REDLED + GREENLED); + + (* начальное состояние светодиодов - включены *) + set_bits(P1OUT, REDLED + GREENLED); + + MSP430.SetIntProc(int); (* назначить обработчик прерываний *) + MSP430.EInt; (* разрешить прерывания *) + + (* инициализация регистров таймера A *) + SYSTEM.PUT(TAR, 0); + SYSTEM.PUT(TACCTL0, CCIE + CAP); + SYSTEM.PUT(TACCR0, 1500); + SYSTEM.PUT(TACTL, TAIE + MC0 + TASSEL0); + + (* инициализация регистров сторожевого таймера *) + set_bits(IE1, WDTIE); + SYSTEM.PUT(WDTCTL, WDTPW + WDTIS1 + WDTSSEL + WDTCNTCL + WDTTMSEL) +END main; + + +BEGIN + main +END TwoTimers. diff --git a/programs/develop/oberon07/Samples/STM32CM3/Blink.ob07 b/programs/develop/oberon07/Samples/STM32CM3/Blink.ob07 new file mode 100644 index 000000000..e2cd4939d --- /dev/null +++ b/programs/develop/oberon07/Samples/STM32CM3/Blink.ob07 @@ -0,0 +1,57 @@ +(* + Пример для STM32L152C-DISCO + + В зависимости от значения константы LED, + мигает синий или зеленый светодиод. +*) + +MODULE Blink; + +IMPORT SYSTEM; + + +CONST + + GPIOB = 40020400H; + GPIOB_MODER = GPIOB; + GPIOB_BSRR = GPIOB + 18H; + + RCC = 40023800H; + RCC_AHBENR = RCC + 1CH; + + Blue = 6; (* PB6 *) + Green = 7; (* PB7 *) + + LED = Blue; + +VAR + + x: SET; + state: BOOLEAN; + + +PROCEDURE Delay (x: INTEGER); +BEGIN + REPEAT + DEC(x) + UNTIL x = 0 +END Delay; + + +BEGIN + (* подключить GPIOB *) + SYSTEM.GET(RCC_AHBENR, x); + SYSTEM.PUT(RCC_AHBENR, x + {1}); + + (* настроить PB6 или PB7 на выход *) + SYSTEM.GET(GPIOB_MODER, x); + SYSTEM.PUT(GPIOB_MODER, x - {LED * 2 - 1} + {LED * 2}); + + state := FALSE; + REPEAT + (* включить или выключить светодиод *) + SYSTEM.PUT(GPIOB_BSRR, {LED + 16 * ORD(state)}); + state := ~state; + Delay(200000) + UNTIL FALSE +END Blink. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/STM32CM3/Button.ob07 b/programs/develop/oberon07/Samples/STM32CM3/Button.ob07 new file mode 100644 index 000000000..aee25eb01 --- /dev/null +++ b/programs/develop/oberon07/Samples/STM32CM3/Button.ob07 @@ -0,0 +1,114 @@ +(* + Пример для STM32L152C-DISCO + + При нажатии на кнопку USER (PA0), меняется + состояние светодиодов. +*) + +MODULE Button; + +IMPORT SYSTEM; + + +CONST + + GPIOA = 40020000H; + GPIOAMODER = GPIOA; + GPIOAOTYPER = GPIOA + 04H; + GPIOAOSPEEDR = GPIOA + 08H; + GPIOAPUPDR = GPIOA + 0CH; + GPIOAIDR = GPIOA + 10H; + GPIOAODR = GPIOA + 14H; + GPIOABSRR = GPIOA + 18H; + GPIOALCKR = GPIOA + 1CH; + GPIOAAFRL = GPIOA + 20H; + GPIOAAFRH = GPIOA + 24H; + GPIOABRR = GPIOA + 28H; + + + GPIOB = 40020400H; + GPIOBMODER = GPIOB; + GPIOBOTYPER = GPIOB + 04H; + GPIOBOSPEEDR = GPIOB + 08H; + GPIOBPUPDR = GPIOB + 0CH; + GPIOBIDR = GPIOB + 10H; + GPIOBODR = GPIOB + 14H; + GPIOBBSRR = GPIOB + 18H; + GPIOBLCKR = GPIOB + 1CH; + GPIOBAFRL = GPIOB + 20H; + GPIOBAFRH = GPIOB + 24H; + GPIOBBRR = GPIOB + 28H; + + + RCC = 40023800H; + RCC_CR = RCC; + RCC_AHBENR = RCC + 1CH; + RCC_APB2ENR = RCC + 20H; + RCC_APB1ENR = RCC + 24H; + + + NVIC = 0E000E100H; + NVIC_ISER0 = NVIC; + NVIC_ISER1 = NVIC + 04H; + NVIC_ISER2 = NVIC + 08H; + + NVIC_ICER0 = NVIC + 80H; + NVIC_ICER1 = NVIC + 84H; + NVIC_ICER2 = NVIC + 88H; + + + EXTI = 040010400H; + EXTI_IMR = EXTI; + EXTI_RTSR = EXTI + 08H; + EXTI_FTSR = EXTI + 0CH; + EXTI_PR = EXTI + 14H; + + + LINE0 = {0}; + + Blue = 6; + Green = 7; + + +VAR + x: SET; + state: INTEGER; + + +(* обработчик прерываний от EXTI0 *) +PROCEDURE PushButton [22]; +BEGIN + SYSTEM.PUT(EXTI_PR, LINE0); (* сбросить флаг прерывания *) + state := (state + 1) MOD 4; + (* изменить состояние светодиодов *) + CASE state OF + |0: SYSTEM.PUT(GPIOBBSRR, {Blue + 16, Green + 16}) + |1: SYSTEM.PUT(GPIOBBSRR, {Blue, Green + 16}) + |2: SYSTEM.PUT(GPIOBBSRR, {Blue + 16, Green}) + |3: SYSTEM.PUT(GPIOBBSRR, {Blue, Green}) + END +END PushButton; + + +BEGIN + state := 0; + + (* подключить GPIOA и GPIOB *) + SYSTEM.GET(RCC_AHBENR, x); + SYSTEM.PUT(RCC_AHBENR, x + {0, 1}); + + (* настроить PB6 и PB7 на выход *) + SYSTEM.GET(GPIOBMODER, x); + SYSTEM.PUT(GPIOBMODER, x + {12, 14} - {13, 15}); + + (* настроить PA0 на вход *) + SYSTEM.GET(GPIOAMODER, x); + SYSTEM.PUT(GPIOAMODER, x - {0, 1}); + + (* разрешить прерывания от EXTI0 (позиция 6) *) + SYSTEM.PUT(NVIC_ISER0, {6}); + + (* разрешить прерывания от LINE0 по нарастающему краю импульса *) + SYSTEM.PUT(EXTI_IMR, LINE0); + SYSTEM.PUT(EXTI_RTSR, LINE0); +END Button. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/STM32CM3/LCD.ob07 b/programs/develop/oberon07/Samples/STM32CM3/LCD.ob07 new file mode 100644 index 000000000..7a3db33cf --- /dev/null +++ b/programs/develop/oberon07/Samples/STM32CM3/LCD.ob07 @@ -0,0 +1,366 @@ +(* + Пример для STM32L152C-DISCO + + Работа со встроенным ЖКИ. + + использовано: + https://habr.com/ru/post/173709/ +*) + +MODULE LCD; + +IMPORT SYSTEM; + + +CONST + + GPIOA = 40020000H; + GPIOAMODER = GPIOA; + GPIOAOTYPER = GPIOA + 04H; + GPIOAOSPEEDR = GPIOA + 08H; + GPIOAPUPDR = GPIOA + 0CH; + GPIOAIDR = GPIOA + 10H; + GPIOAODR = GPIOA + 14H; + GPIOABSRR = GPIOA + 18H; + GPIOALCKR = GPIOA + 1CH; + GPIOAAFRL = GPIOA + 20H; + GPIOAAFRH = GPIOA + 24H; + GPIOABRR = GPIOA + 28H; + + + GPIOB = 40020400H; + GPIOBMODER = GPIOB; + GPIOBOTYPER = GPIOB + 04H; + GPIOBOSPEEDR = GPIOB + 08H; + GPIOBPUPDR = GPIOB + 0CH; + GPIOBIDR = GPIOB + 10H; + GPIOBODR = GPIOB + 14H; + GPIOBBSRR = GPIOB + 18H; + GPIOBLCKR = GPIOB + 1CH; + GPIOBAFRL = GPIOB + 20H; + GPIOBAFRH = GPIOB + 24H; + GPIOBBRR = GPIOB + 28H; + + + GPIOC = 40020800H; + GPIOCMODER = GPIOC; + GPIOCOTYPER = GPIOC + 04H; + GPIOCOSPEEDR = GPIOC + 08H; + GPIOCPUPDR = GPIOC + 0CH; + GPIOCIDR = GPIOC + 10H; + GPIOCODR = GPIOC + 14H; + GPIOCBSRR = GPIOC + 18H; + GPIOCLCKR = GPIOC + 1CH; + GPIOCAFRL = GPIOC + 20H; + GPIOCAFRH = GPIOC + 24H; + GPIOCBRR = GPIOC + 28H; + + + RCC = 40023800H; + RCC_CR = RCC; + RCC_AHBENR = RCC + 1CH; + RCC_APB2ENR = RCC + 20H; + RCC_APB1ENR = RCC + 24H; + RCC_CSR = RCC + 34H; + + + PWR = 40007000H; + PWR_CR = PWR; + + + LCD = 40002400H; + LCD_CR = LCD; + LCD_FCR = LCD + 04H; + LCD_SR = LCD + 08H; + LCD_RAM = LCD + 14H; + + + AFM = 2; + + AF11 = 11; + + PinsA = {1..3, 8..10, 15}; + PinsB = {3..5, 8..15}; + PinsC = {0..3, 6..11}; + + A = 0; H = 7; + B = 1; J = 8; + C = 2; K = 9; + D = 3; M = 10; + E = 4; N = 11; + F = 5; P = 12; + G = 6; Q = 13; + + DP = 14; COLON = 15; BAR = 16; + + +VAR + display: ARRAY 6, 17 OF INTEGER; + + digits: ARRAY 10 OF SET; + + +PROCEDURE SetPinsMode (reg: INTEGER; pins: SET; mode: INTEGER); +VAR + x: SET; + pin: INTEGER; + +BEGIN + mode := mode MOD 4; + SYSTEM.GET(reg, x); + FOR pin := 0 TO 30 BY 2 DO + IF (pin DIV 2) IN pins THEN + x := x - {pin, pin + 1} + BITS(LSL(mode, pin)) + END + END; + SYSTEM.PUT(reg, x) +END SetPinsMode; + + +PROCEDURE SRBits (adr: INTEGER; setbits, resetbits: SET); +VAR + x: SET; + +BEGIN + SYSTEM.GET(adr, x); + SYSTEM.PUT(adr, x - resetbits + setbits) +END SRBits; + + +PROCEDURE SetBits (adr: INTEGER; bits: SET); +VAR + x: SET; + +BEGIN + SYSTEM.GET(adr, x); + SYSTEM.PUT(adr, x + bits) +END SetBits; + + +PROCEDURE ResetBits (adr: INTEGER; bits: SET); +VAR + x: SET; + +BEGIN + SYSTEM.GET(adr, x); + SYSTEM.PUT(adr, x - bits) +END ResetBits; + + +PROCEDURE TestBits (adr: INTEGER; bits: SET): BOOLEAN; +VAR + x: SET; + +BEGIN + SYSTEM.GET(adr, x); + RETURN x * bits = bits +END TestBits; + + +PROCEDURE Init; +VAR + i, j: INTEGER; + seg: ARRAY 30 OF INTEGER; + +BEGIN + FOR i := 0 TO 29 DO + seg[i] := i + END; + + FOR i := 3 TO 11 DO + seg[i] := i + 4 + END; + + seg[18] := 17; + seg[19] := 16; + + FOR i := 20 TO 23 DO + seg[i] := i - 2 + END; + + j := 0; + FOR i := 0 TO 5 DO + display[i, A] := 256 + seg[28 - j]; + display[i, B] := 0 + seg[28 - j]; + display[i, C] := 256 + seg[j + 1]; + display[i, D] := 256 + seg[j]; + display[i, E] := 0 + seg[j]; + display[i, F] := 256 + seg[29 - j]; + display[i, G] := 0 + seg[29 - j]; + display[i, H] := 768 + seg[29 - j]; + display[i, J] := 768 + seg[28 - j]; + display[i, K] := 512 + seg[28 - j]; + display[i, M] := 0 + seg[j + 1]; + display[i, N] := 768 + seg[j]; + display[i, P] := 512 + seg[j]; + display[i, Q] := 512 + seg[29 - j]; + INC(j, 2) + END; + + display[0, DP] := 768 + 1; + display[1, DP] := 768 + 7; + display[2, DP] := 768 + 9; + display[3, DP] := 768 + 11; + + display[0, COLON] := 512 + 1; + display[1, COLON] := 512 + 7; + display[2, COLON] := 512 + 9; + display[3, COLON] := 512 + 11; + + display[0, BAR] := 768 + 15; + display[1, BAR] := 512 + 15; + display[2, BAR] := 768 + 13; + display[3, BAR] := 512 + 13; + + digits[0] := {A, B, C, D, E, F}; + digits[1] := {B, C}; + digits[2] := {A, B, M, G, E, D}; + digits[3] := {A, B, M, G, C, D}; + digits[4] := {F, G, M, B, C}; + digits[5] := {A, F, G, M, C, D}; + digits[6] := {A, F, G, M, C, D, E}; + digits[7] := {F, A, B, C}; + digits[8] := {A, B, C, D, E, F, G, M}; + digits[9] := {A, B, C, D, F, G, M}; +END Init; + + +PROCEDURE ResetSeg (seg: INTEGER); +BEGIN + ResetBits(LCD_RAM + (seg DIV 256) * 2 * 4, {seg MOD 256}) +END ResetSeg; + + +PROCEDURE SetSeg (seg: INTEGER); +BEGIN + SetBits(LCD_RAM + (seg DIV 256) * 2 * 4, {seg MOD 256}) +END SetSeg; + + +PROCEDURE Digit (pos, dgt: INTEGER); +VAR + s: SET; + i: INTEGER; + +BEGIN + s := digits[dgt]; + FOR i := 0 TO 13 DO + IF i IN s THEN + SetSeg(display[pos, i]) + ELSE + ResetSeg(display[pos, i]) + END + END +END Digit; + + +PROCEDURE WhileBits (adr: INTEGER; bits: SET); +BEGIN + WHILE TestBits(adr, bits) DO END +END WhileBits; + + +PROCEDURE UntilBits (adr: INTEGER; bits: SET); +BEGIN + REPEAT UNTIL TestBits(adr, bits) +END UntilBits; + + +PROCEDURE main; +VAR + i: INTEGER; + +BEGIN + Init; + + (* подключить GPIOA, GPIOB, GPIOC *) + SetBits(RCC_AHBENR, {0, 1, 2}); + + (* настроить на режим альтернативной функции *) + SetPinsMode(GPIOAMODER, PinsA, AFM); + + (* 400 кГц *) + SetPinsMode(GPIOAOSPEEDR, PinsA, 0); + + (* без подтягивающих резисторов *) + SetPinsMode(GPIOAPUPDR, PinsA, 0); + + (* режим push-pull *) + ResetBits(GPIOAOTYPER, PinsA); + + (* альтернативная функция AF11 = 0BH *) + SYSTEM.PUT(GPIOAAFRL, 0BBB0H); + SYSTEM.PUT(GPIOAAFRH, 0B0000BBBH); + + (* аналогично для GPIOB *) + SetPinsMode(GPIOBMODER, PinsB, AFM); + SetPinsMode(GPIOBOSPEEDR, PinsB, 0); + SetPinsMode(GPIOBPUPDR, PinsB, 0); + ResetBits(GPIOBOTYPER, PinsB); + SYSTEM.PUT(GPIOBAFRL, 000BBB000H); + SYSTEM.PUT(GPIOBAFRH, 0BBBBBBBBH); + + (* аналогично для GPIOC *) + SetPinsMode(GPIOCMODER, PinsC, AFM); + SetPinsMode(GPIOCOSPEEDR, PinsC, 0); + SetPinsMode(GPIOCPUPDR, PinsC, 0); + ResetBits(GPIOCOTYPER, PinsC); + SYSTEM.PUT(GPIOCAFRL, 0BB00BBBBH); + SYSTEM.PUT(GPIOCAFRH, 00000BBBBH); + + (* подключить контроллер ЖКИ *) + SetBits(RCC_APB1ENR, {9, 28}); (* LCDEN = {9}; PWREN = {28} *) + + (* разрешить запись в регистр RCC_CSR *) + SetBits(PWR_CR, {8}); (* DBP = {8} *) + + (* сбросить источник тактирования *) + SetBits(RCC_CSR, {23}); (* RTCRST = {23} *) + + (* выбрать новый источник *) + ResetBits(RCC_CSR, {23}); (* RTCRST = {23} *) + + (* включить НЧ генератор *) + SetBits(RCC_CSR, {8}); (* LSEON = {8} *) + + (* ждать готовность НЧ генератора *) + UntilBits(RCC_CSR, {9}); (* LSERDY = {9} *) + + (* выбрать НЧ генератор как источник тактирования *) + SRBits(RCC_CSR, {16}, {17}); (* RCC_CSR[17:16] := 01b *) + + (* настроить контроллер ЖКИ *) + SRBits(LCD_CR, {2, 3, 6, 7}, {4, 5}); (* MUX_SEG = {7}; BIAS1 = {6}; BIAS0 = {5}; DUTY2 = {4}; DUTY1 = {3}; DUTY0 = {2} *) + + (* Установить значения коэффициентов деления частоты тактового сигнала LCDCLK *) + SRBits(LCD_FCR, {11, 18, 24}, {10..12, 18..25}); (* LCD_FCR[12:10] := 010b; LCD_FCR[21:18] := 0001b; LCD_FCR[25:22] := 0100b *) + + (* ждать синхронизацию регистра LCD_FCR *) + UntilBits(LCD_SR, {5}); (* FCRSF = {5} *) + + (* выбрать внутренний источник напряжения для ЖКИ и разрешить его работу *) + SRBits(LCD_CR, {0}, {1}); (* LCD_CR_VSEL = {1}; LCD_CR_LCDEN = {0} *) + + (* ждать готовность контроллера ЖКИ *) + UntilBits(LCD_SR, {0, 4}); (* LCD_SR_RDY = {4}; LCD_SR_ENS = {0} *) + + (* ждать завершение предыдущей записи *) + WhileBits(LCD_SR, {2}); (* LCD_SR_UDR = {2} *) + + (* начать запись *) + FOR i := 0 TO 5 DO + Digit(i, i + 1) (* 123456 *) + END; + + SetSeg(display[1, DP]); (* 12.3456 *) + SetSeg(display[3, COLON]); (* 12.34:56 *) + SetSeg(display[0, BAR]); (* 12.34:56_ *) + + (* завершить запись *) + SetBits(LCD_SR, {2}) (* LCD_SR_UDR = {2} *) +END main; + + +BEGIN + main +END LCD. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/STM32CM3/SysTick.ob07 b/programs/develop/oberon07/Samples/STM32CM3/SysTick.ob07 new file mode 100644 index 000000000..7db04948f --- /dev/null +++ b/programs/develop/oberon07/Samples/STM32CM3/SysTick.ob07 @@ -0,0 +1,79 @@ +(* + Пример для STM32L152C-DISCO + + Светодиоды мигают по прерыванию от системного таймера. +*) + +MODULE SysTick; + +IMPORT SYSTEM; + + +CONST + + GPIOB = 40020400H; + GPIOBMODER = GPIOB; + GPIOBOTYPER = GPIOB + 04H; + GPIOBOSPEEDR = GPIOB + 08H; + GPIOBPUPDR = GPIOB + 0CH; + GPIOBIDR = GPIOB + 10H; + GPIOBODR = GPIOB + 14H; + GPIOBBSRR = GPIOB + 18H; + GPIOBLCKR = GPIOB + 1CH; + GPIOBAFRL = GPIOB + 20H; + GPIOBAFRH = GPIOB + 24H; + GPIOBBRR = GPIOB + 28H; + + + RCC = 40023800H; + RCC_CR = RCC; + RCC_AHBENR = RCC + 1CH; + RCC_APB2ENR = RCC + 20H; + RCC_APB1ENR = RCC + 24H; + + + STK = 0E000E010H; + STK_CTRL = STK; + ENABLE = {0}; + TICKINT = {1}; + CLKSOURCE = {2}; + + STK_LOAD = STK + 04H; + STK_VAL = STK + 08H; + STK_CALIB = STK + 0CH; + + + Blue = 6; + Green = 7; + + +VAR + + x: SET; state: BOOLEAN; + + +(* обработчик прерываний от System tick timer *) +PROCEDURE tick [15]; +BEGIN + state := ~state; + (* включить или выключить светодиоды *) + SYSTEM.PUT(GPIOBBSRR, {Blue + 16 * ORD(state)}); + SYSTEM.PUT(GPIOBBSRR, {Green + 16 * ORD(state)}) +END tick; + + +BEGIN + state := FALSE; + + (* подключить GPIOB *) + SYSTEM.GET(RCC_AHBENR, x); + SYSTEM.PUT(RCC_AHBENR, x + {1}); + + (* настроить PB6 и PB7 на выход *) + SYSTEM.GET(GPIOBMODER, x); + SYSTEM.PUT(GPIOBMODER, x + {12, 14} - {13, 15}); + + (* настроить и запустить SysTick *) + SYSTEM.PUT(STK_LOAD, 1048576); + SYSTEM.PUT(STK_CTRL, ENABLE + TICKINT + CLKSOURCE); +END SysTick. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/STM32CM3/TIM67.ob07 b/programs/develop/oberon07/Samples/STM32CM3/TIM67.ob07 new file mode 100644 index 000000000..64b536ea9 --- /dev/null +++ b/programs/develop/oberon07/Samples/STM32CM3/TIM67.ob07 @@ -0,0 +1,143 @@ +(* + Пример для STM32L152C-DISCO + + Синий светодиод мигает по прерыванию от таймера TIM6, + зеленый - от TIM7. +*) + +MODULE TIM67; + +IMPORT SYSTEM; + + +CONST + + GPIOB = 40020400H; + GPIOBMODER = GPIOB; + GPIOBOTYPER = GPIOB + 04H; + GPIOBOSPEEDR = GPIOB + 08H; + GPIOBPUPDR = GPIOB + 0CH; + GPIOBIDR = GPIOB + 10H; + GPIOBODR = GPIOB + 14H; + GPIOBBSRR = GPIOB + 18H; + GPIOBLCKR = GPIOB + 1CH; + GPIOBAFRL = GPIOB + 20H; + GPIOBAFRH = GPIOB + 24H; + GPIOBBRR = GPIOB + 28H; + + + RCC = 40023800H; + RCC_CR = RCC; + RCC_AHBENR = RCC + 1CH; + RCC_APB2ENR = RCC + 20H; + RCC_APB1ENR = RCC + 24H; + + + TIM6 = 40001000H; + TIM6_CR1 = TIM6; + CEN = {0}; + UDIS = {1}; + URS = {2}; + OPM = {3}; + ARPE = {7}; + + TIM6_CR2 = TIM6 + 04H; + + TIM6_DIER = TIM6 + 0CH; + UIE = {0}; + + TIM6_SR = TIM6 + 10H; + UIF = {0}; + + TIM6_EGR = TIM6 + 14H; + UG = {0}; + + TIM6_CNT = TIM6 + 24H; + TIM6_PSC = TIM6 + 28H; + TIM6_ARR = TIM6 + 2CH; + + + TIM7 = 40001400H; + TIM7_CR1 = TIM7; + TIM7_CR2 = TIM7 + 04H; + TIM7_DIER = TIM7 + 0CH; + TIM7_SR = TIM7 + 10H; + TIM7_EGR = TIM7 + 14H; + TIM7_CNT = TIM7 + 24H; + TIM7_PSC = TIM7 + 28H; + TIM7_ARR = TIM7 + 2CH; + + + NVIC = 0E000E100H; + NVIC_ISER0 = NVIC; + NVIC_ISER1 = NVIC + 04H; + NVIC_ISER2 = NVIC + 08H; + + NVIC_ICER0 = NVIC + 80H; + NVIC_ICER1 = NVIC + 84H; + NVIC_ICER2 = NVIC + 88H; + + + BLUELED = 6; + GREENLED = 7; + + +VAR + x: SET; + state1, state2: BOOLEAN; + + +(* обработчик прерываний от TIM6 *) +PROCEDURE tim6 [59]; +BEGIN + SYSTEM.PUT(TIM6_SR, 0); (* сбросить флаг прерывания *) + state1 := ~state1; + (* включить или выключить синий светодиод *) + SYSTEM.PUT(GPIOBBSRR, {BLUELED + 16 * ORD(state1)}) + +END tim6; + + +(* обработчик прерываний от TIM7 *) +PROCEDURE tim7 [60]; +BEGIN + SYSTEM.PUT(TIM7_SR, 0); (* сбросить флаг прерывания *) + state2 := ~state2; + (* включить или выключить зеленый светодиод *) + SYSTEM.PUT(GPIOBBSRR, {GREENLED + 16 * ORD(state2)}) +END tim7; + + +BEGIN + state1 := FALSE; + state2 := FALSE; + + (* подключить GPIOB *) + SYSTEM.GET(RCC_AHBENR, x); + SYSTEM.PUT(RCC_AHBENR, x + {1}); + + (* подключить TIM6 и TIM7 *) + SYSTEM.GET(RCC_APB1ENR, x); + SYSTEM.PUT(RCC_APB1ENR, x + {4, 5}); + + (* настроить PB6 и PB7 на выход *) + SYSTEM.GET(GPIOBMODER, x); + SYSTEM.PUT(GPIOBMODER, x + {12, 14} - {13, 15}); + + (* разрешить прерывания от таймеров TIM6 (позиция 43) и TIM7 (позиция 44) *) + SYSTEM.PUT(NVIC_ISER1, {11, 12}); + + (* настроить и запустить TIM6 *) + SYSTEM.PUT(TIM6_ARR, 31); + SYSTEM.PUT(TIM6_PSC, 65535); + SYSTEM.PUT(TIM6_DIER, UIE); + SYSTEM.GET(TIM6_CR1, x); + SYSTEM.PUT(TIM6_CR1, x + CEN - (UDIS + URS + OPM + ARPE)); + + (* настроить и запустить TIM7 *) + SYSTEM.PUT(TIM7_ARR, 8000); + SYSTEM.PUT(TIM7_PSC, 80); + SYSTEM.PUT(TIM7_DIER, UIE); + SYSTEM.GET(TIM7_CR1, x); + SYSTEM.PUT(TIM7_CR1, x + CEN - (UDIS + URS + OPM + ARPE)); +END TIM67. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/Windows/Console/Doors.ob07 b/programs/develop/oberon07/Samples/Windows/Console/Doors.ob07 new file mode 100644 index 000000000..838137411 --- /dev/null +++ b/programs/develop/oberon07/Samples/Windows/Console/Doors.ob07 @@ -0,0 +1,58 @@ +(* + adapted to Oberon-07 by 0CodErr, KolibriOS team + *) +(* + There are 100 doors in a row that are all initially closed. + You make 100 passes by the doors. + The first time through, visit every door and toggle the door (if the door is closed, open it; if it is open, close it). + The second time, only visit every 2nd door (door #2, #4, #6, ...), and toggle it. + The third time, visit every 3rd door (door #3, #6, #9, ...), etc, until you only visit the 100th door. + What state are the doors in after the last pass? Which are open, which are closed? +*) +MODULE Doors; + +IMPORT In, Out, Console; + + +CONST + CLOSED = FALSE; + OPEN = TRUE; + + +TYPE + List = ARRAY 101 OF BOOLEAN; + + +VAR + Doors: List; + I, J: INTEGER; + + +BEGIN + Console.open; + + FOR I := 1 TO 100 DO + FOR J := 1 TO 100 DO + IF J MOD I = 0 THEN + IF Doors[J] = CLOSED THEN + Doors[J] := OPEN + ELSE + Doors[J] := CLOSED + END + END + END + END; + FOR I := 1 TO 100 DO + Out.Int(I, 3); + Out.String(" is "); + IF Doors[I] = CLOSED THEN + Out.String("Closed.") + ELSE + Out.String("Open.") + END; + Out.Ln + END; + In.Ln; + + Console.exit(TRUE) +END Doors. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/Windows/Console/HeapSort.ob07 b/programs/develop/oberon07/Samples/Windows/Console/HeapSort.ob07 new file mode 100644 index 000000000..745970ee4 --- /dev/null +++ b/programs/develop/oberon07/Samples/Windows/Console/HeapSort.ob07 @@ -0,0 +1,101 @@ +(* + adapted to Oberon-07 by 0CodErr, KolibriOS team + *) +(* ********* Zonnon online collection *********** + * Sorting: Heap Sort (Chapter 2, Example 2.8) + * + * This example is a part of Prof. Nikalus Wirth's book + * www.zonnon.ethz.ch/usergroup + * (c) ETH Zurich + *) + +MODULE HeapSort; + +IMPORT In, Out, Console; + + +CONST + MAX_SIZE = 20; + + +TYPE + DefaultArray = ARRAY MAX_SIZE OF INTEGER; + + +VAR + MyArray: DefaultArray; + + (***** Implementation *****) + +PROCEDURE sift(VAR a: DefaultArray; L,R:INTEGER); +VAR + i, j, x: INTEGER; + +BEGIN + i := L; j:= 2 * L; x:= a[L]; + IF (j < R) & (a[j] < a[j + 1]) THEN j := j + 1 END; + WHILE (j <= R) & (x < a[j]) DO + a[i] := a[j]; i := j; j := 2 * j; + IF (j < R) & (a[j] < a[j + 1]) THEN j := j + 1 END + END; + a[i] := x +END sift; + + +PROCEDURE HeapSort(VAR a: DefaultArray; n: INTEGER); +VAR + L, R, x: INTEGER; + +BEGIN + L := (n DIV 2); R := n - 1; + WHILE L > 0 DO L := L - 1; sift(a, L, R) END; + WHILE R > 0 DO + x := a[0]; a[0] := a[R]; a[R]:= x; + R := R - 1; sift(a, L, R) + END +END HeapSort; + +(***** Example support *****) + +PROCEDURE FillTheArray; +VAR + i: INTEGER; + +BEGIN + FOR i := 0 TO MAX_SIZE - 1 DO + MyArray[i] := ABS(10 - i) + END +END FillTheArray; + + +PROCEDURE PrintTheArray; +VAR + i: INTEGER; + +BEGIN + Out.String("Array:"); Out.Ln; + FOR i := 0 TO MAX_SIZE - 1 DO + Out.Int(MyArray[i], 2); Out.String(", ") + END; + Out.Ln +END PrintTheArray; + + +PROCEDURE Execute; +BEGIN + HeapSort(MyArray, MAX_SIZE) +END Execute; + + +BEGIN + Console.open; + + Out.String("Example 2.8 (Heap sort)"); Out.Ln; + FillTheArray; + PrintTheArray; + Execute; + PrintTheArray; + Out.String("Press Enter to continue"); In.Ln; + + Console.exit(TRUE) +END HeapSort. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/Windows/Console/Hello.ob07 b/programs/develop/oberon07/Samples/Windows/Console/Hello.ob07 new file mode 100644 index 000000000..e40d3fe04 --- /dev/null +++ b/programs/develop/oberon07/Samples/Windows/Console/Hello.ob07 @@ -0,0 +1,13 @@ +MODULE Hello; + +IMPORT Console, In, Out; + + +BEGIN + Console.open; + + Out.String("Hello, world!"); + In.Ln; + + Console.exit(TRUE) +END Hello. diff --git a/programs/develop/oberon07/Samples/Windows/Console/HelloRus.ob07 b/programs/develop/oberon07/Samples/Windows/Console/HelloRus.ob07 new file mode 100644 index 000000000..5036196bb --- /dev/null +++ b/programs/develop/oberon07/Samples/Windows/Console/HelloRus.ob07 @@ -0,0 +1,26 @@ +MODULE HelloRus; + +IMPORT Console, In, Out; + + +PROCEDURE main; +VAR + str: ARRAY 10 OF WCHAR; + +BEGIN + str := "Привет!"; + Out.StringW(str); Out.Ln; + str[2] := "е"; + str[5] := "д"; + Out.StringW(str) +END main; + + +BEGIN + Console.open; + + main; + In.Ln; + + Console.exit(TRUE) +END HelloRus. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/Windows/Console/MagicSquares.ob07 b/programs/develop/oberon07/Samples/Windows/Console/MagicSquares.ob07 new file mode 100644 index 000000000..8dce19834 --- /dev/null +++ b/programs/develop/oberon07/Samples/Windows/Console/MagicSquares.ob07 @@ -0,0 +1,48 @@ +(* + adapted to Oberon-07 by 0CodErr, KolibriOS team + *) +(* ********* Zonnon online collection *********** + * Magic Squares + * + * This example is a part of Prof. Nikalus Wirth's book + * www.zonnon.ethz.ch/usergroup + * (c) ETH Zurich + *) + +MODULE MagicSquares; (*NW 11.8.97*) + +IMPORT In, Out, Console; + + +PROCEDURE Generate; (*magic square of order 3, 5, 7, ... *) +VAR + i, j, x, nx, nsq, n: INTEGER; + M: ARRAY 13, 13 OF INTEGER; + +BEGIN + Out.String("Enter magic square order(3, 5, 7, ..., 13): "); In.Int(n); nsq := n * n; x := 0; + i := n DIV 2; j := n - 1; + WHILE x < nsq DO + nx := n + x; j := (j - 1) MOD n; INC(x); + Out.Int(i, 1); Out.Char(9X); + Out.Int(j, 1); Out.Ln; + M[i, j] := x; + WHILE x < nx DO + i := (i + 1) MOD n; j := (j + 1) MOD n; + INC(x); M[i, j] := x + END + END; + FOR i := 0 TO n - 1 DO + FOR j := 0 TO n - 1 DO Out.Int(M[i, j], 6) END; + Out.Ln + END +END Generate; + +BEGIN + Console.open; + + Generate; + Out.String("Press Enter to continue"); In.Ln; + + Console.exit(TRUE) +END MagicSquares. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/Windows/Console/MultiplicationTables.ob07 b/programs/develop/oberon07/Samples/Windows/Console/MultiplicationTables.ob07 new file mode 100644 index 000000000..434e3724d --- /dev/null +++ b/programs/develop/oberon07/Samples/Windows/Console/MultiplicationTables.ob07 @@ -0,0 +1,52 @@ +(* + adapted to Oberon-07 by 0CodErr, KolibriOS team + *) +(* + Produce a formatted NxN multiplication table + Only print the top half triangle of products +*) + +MODULE MultiplicationTables; + +IMPORT In, Out, Console; + + +CONST + N = 18; + + +VAR + I, J: INTEGER; + + +BEGIN + Console.open; + + FOR J := 1 TO N - 1 DO + Out.Int(J, 3); + Out.String(" ") + END; + Out.Int(N, 3); + Out.Ln; + FOR J := 0 TO N - 1 DO + Out.String("----") + END; + Out.String("+"); + Out.Ln; + FOR I := 1 TO N DO + FOR J := 1 TO N DO + IF J < I THEN + Out.String(" ") + ELSE + Out.Int(I * J, 3); + Out.String(" ") + END + END; + Out.String("| "); + Out.Int(I, 2); + Out.Ln + END; + In.Ln; + + Console.exit(TRUE) +END MultiplicationTables. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/Windows/Console/SierpinskiCarpet.ob07 b/programs/develop/oberon07/Samples/Windows/Console/SierpinskiCarpet.ob07 new file mode 100644 index 000000000..53e48b1eb --- /dev/null +++ b/programs/develop/oberon07/Samples/Windows/Console/SierpinskiCarpet.ob07 @@ -0,0 +1,75 @@ +(* + adapted to Oberon-07 by 0CodErr, KolibriOS team + *) +MODULE SierpinskiCarpet; + +IMPORT In, Out, Console; + + +VAR + order: INTEGER; + + +PROCEDURE pow(b, n: INTEGER): INTEGER; +VAR + i, res: INTEGER; + +BEGIN + res := 1; + FOR i := 1 TO n DO + res := res * b + END + + RETURN res +END pow; + + +PROCEDURE in_carpet(x, y: INTEGER): BOOLEAN; +VAR + res, exit: BOOLEAN; + +BEGIN + exit := FALSE; + res := TRUE; + WHILE (x > 0) & (y > 0) & (exit = FALSE) DO + IF (x MOD 3 = 1) & (y MOD 3 = 1) THEN + res := FALSE; + exit := TRUE + END; + y := y DIV 3; + x := x DIV 3 + END + + RETURN res +END in_carpet; + + +PROCEDURE PrintSierpinski(n: INTEGER); +VAR + i, j, l: INTEGER; + +BEGIN + l := pow(3, n) - 1; + FOR i := 0 TO l DO + FOR j := 0 TO l DO + IF in_carpet(i, j) THEN + Out.Char("#") + ELSE + Out.Char(" ") + END + END; + Out.Ln + END +END PrintSierpinski; + + +BEGIN + Console.open; + + Out.String("Input carpet order(0..3):"); + In.Int(order); + PrintSierpinski(order); + In.Ln; + + Console.exit(TRUE) +END SierpinskiCarpet. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/Windows/Console/SierpinskiTriangle.ob07 b/programs/develop/oberon07/Samples/Windows/Console/SierpinskiTriangle.ob07 new file mode 100644 index 000000000..c72607ffe --- /dev/null +++ b/programs/develop/oberon07/Samples/Windows/Console/SierpinskiTriangle.ob07 @@ -0,0 +1,44 @@ +(* + adapted to Oberon-07 by 0CodErr, KolibriOS team + *) +MODULE SierpinskiTriangle; + +IMPORT In, Out, Console; + + +VAR + order: INTEGER; + + +PROCEDURE PrintSierpinski(order: INTEGER); +VAR + x, y, k, size: INTEGER; + +BEGIN + size := LSL(1, order) - 1; + FOR y := size TO 0 BY -1 DO + FOR k := 1 TO y DO + Out.Char(" ") + END; + FOR x := 0 TO size - y DO + IF BITS(x) * BITS(y) = {} THEN + Out.String("* ") + ELSE + Out.String(" ") + END + END; + Out.Ln + END +END PrintSierpinski; + + +BEGIN + Console.open; + + Out.String("Input triangle order(0..5):"); + In.Int(order); + PrintSierpinski(order); + In.Ln; + + Console.exit(TRUE) +END SierpinskiTriangle. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/Windows/Console/Sieve.ob07 b/programs/develop/oberon07/Samples/Windows/Console/Sieve.ob07 new file mode 100644 index 000000000..a0a6460f3 --- /dev/null +++ b/programs/develop/oberon07/Samples/Windows/Console/Sieve.ob07 @@ -0,0 +1,51 @@ +(* + adapted to Oberon-07 by 0CodErr, KolibriOS team + *) + +(* This was taken from the CRITICAL MASS MODULA-3 examples *) + +(* The "Sieve" program demonstrates the use of arrays, + loops and conditionals. *) + +MODULE Sieve; + +IMPORT In, Out, Console; + +(* Search in interval 2 to 1000 for prime numbers. *) +CONST + LastNum = 1000; + +(* "prime" is an array of booleans ranging from 2 to "LastNum". *) +VAR + prime: ARRAY LastNum + 2 OF BOOLEAN; + i, j: INTEGER; + +BEGIN + Console.open; + + Out.String("Primes in range 2.."); Out.Int(LastNum, 1); Out.Char(":"); Out.Ln; +(* Initialize all elements of the array to "TRUE". + (Note that we could have initialized the array during + the assignment.) *) + FOR i := 2 TO LastNum DO + prime[i] := TRUE + END; +(* Loop through all integers between 2 and "LastNum". Print each prime + number, starting from 2 and mark all numbers that are divisible by + that prime number to "FALSE". Repeat the step until we've exhausted + all the numbers in the interval.*) + FOR i := 2 TO LastNum DO + IF prime[i] THEN + Out.Int(i, 3); + Out.Char(" "); + FOR j := i TO LastNum DO + IF j MOD i = 0 THEN + prime[j] := FALSE + END + END + END + END; + Out.Ln; In.Ln; + + Console.exit(TRUE) +END Sieve. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/Windows/Console/SpiralMatrix.ob07 b/programs/develop/oberon07/Samples/Windows/Console/SpiralMatrix.ob07 new file mode 100644 index 000000000..223952085 --- /dev/null +++ b/programs/develop/oberon07/Samples/Windows/Console/SpiralMatrix.ob07 @@ -0,0 +1,56 @@ +(* + adapted to Oberon-07 by 0CodErr, KolibriOS team + *) +(* + Produce a spiral array. + A spiral array is a square arrangement of the first (Width * Height) natural numbers, + where the numbers increase sequentially as you go around the edges of the array spiraling inwards. +*) + +MODULE SpiralMatrix; + +IMPORT In, Out, Console; + + +VAR + Width, Height: INTEGER; + + +PROCEDURE spiral(w, h, x, y: INTEGER): INTEGER; +VAR + res: INTEGER; + +BEGIN + IF y # 0 THEN + res := w + spiral(h - 1, w, y - 1, w - x - 1) + ELSE + res := x + END + RETURN res +END spiral; + + +PROCEDURE print_spiral(w, h: INTEGER); +VAR + i, j: INTEGER; + +BEGIN + FOR i := 0 TO h - 1 DO + FOR j := 0 TO w - 1 DO + Out.Int(spiral(w, h, j, i), 4) + END; + Out.Ln + END +END print_spiral; + + +BEGIN + Console.open; + + Out.String("Input width of matrix(1, 2, 3, ...):"); In.Int(Width); + Out.String("Input height of matrix:(1, 2, 3, ...)"); In.Int(Height); + print_spiral(Width, Height); + In.Ln; + + Console.exit(TRUE) +END SpiralMatrix. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/Windows/Console/TempConv.ob07 b/programs/develop/oberon07/Samples/Windows/Console/TempConv.ob07 new file mode 100644 index 000000000..6906af1e7 --- /dev/null +++ b/programs/develop/oberon07/Samples/Windows/Console/TempConv.ob07 @@ -0,0 +1,44 @@ +(* + adapted to Oberon-07 by 0CodErr, KolibriOS team + *) +(* This program is a good example of proper formatting, it is *) +(* easy to read and very easy to understand. It should be a *) +(* snap to update a program that is well written like this. You *) +(* should begin to develop good formatting practice early in *) +(* your programming career. *) + +MODULE TempConv; + +IMPORT In, Out, Console; + + +VAR + Count : INTEGER; (* a variable used for counting *) + Centigrade : INTEGER; (* the temperature in centigrade *) + Farenheit : INTEGER; (* the temperature in farenheit *) + +BEGIN + Console.open; + + Out.String("Farenheit to Centigrade temperature table"); + Out.Ln; + Out.Ln; + FOR Count := -2 TO 12 DO + Centigrade := 10 * Count; + Farenheit := 32 + Centigrade * 9 DIV 5; + Out.String(" C ="); + Out.Int(Centigrade, 5); + Out.String(" F ="); + Out.Int(Farenheit, 5); + IF Centigrade = 0 THEN + Out.String(" Freezing point of water"); + END; + IF Centigrade = 100 THEN + Out.String(" Boiling point of water"); + END; + Out.Ln; + END; (* of main loop *) + In.Ln; + + Console.exit(TRUE) +END TempConv. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/Windows/Console/exp.ob07 b/programs/develop/oberon07/Samples/Windows/Console/exp.ob07 new file mode 100644 index 000000000..39807377a --- /dev/null +++ b/programs/develop/oberon07/Samples/Windows/Console/exp.ob07 @@ -0,0 +1,117 @@ +(* + adapted to Oberon-07 by 0CodErr, KolibriOS team + *) +(* Print first 'PRINT' digits of 'e'. + * + * Originally written in Pascal by Scott Hemphill + * Rewritten in Modula-2 and modified by Andrew Cadach + * + *) + +MODULE exp; + +IMPORT In, Out, Console; + + +CONST + PRINT = 1024; + DIGITS = PRINT + (PRINT + 31) DIV 32; + + +TYPE + number = ARRAY DIGITS + 1 OF INTEGER; + + +VAR + s, x: number; + xs, i: INTEGER; + + +PROCEDURE init (VAR x: number; n: INTEGER); +VAR + i: INTEGER; + +BEGIN + x[0] := n; + FOR i := 1 TO DIGITS DO x[i] := 0 END +END init; + + +PROCEDURE divide (VAR x: number; xs, n: INTEGER; + VAR y: number; VAR ys: INTEGER); +VAR + i, c: INTEGER; + +BEGIN + c := 0; + FOR i := xs TO DIGITS DO + c := 10 * c + x[i]; + y[i] := c DIV n; + c := c MOD n + END; + ys := xs; + WHILE (ys <= DIGITS) & (y[ys] = 0) DO INC(ys) END +END divide; + + +PROCEDURE add (VAR s, x: number; xs: INTEGER); +VAR + i, c: INTEGER; +BEGIN + c := 0; + FOR i := DIGITS TO xs BY -1 DO + c := c + s[i] + x[i]; + IF c >= 10 THEN + s[i] := c - 10; + c := 1 + ELSE + s[i] := c; + c := 0 + END + END; + i := xs; + WHILE c # 0 DO + DEC(i); + c := c + s[i]; + IF c >= 10 THEN + s[i] := c - 10; + c := 1 + ELSE + s[i] := c; + c := 0 + END + END +END add; + + +BEGIN + Console.open; + + init(s, 0); + init(x, 1); + xs := 0; + add(s, x, xs); + i := 0; + REPEAT + INC(i); + divide(x, xs, i, x, xs); + add(s, x, xs); + UNTIL xs > DIGITS; + Out.Ln; + Out.String (" e = "); + Out.Char (CHR(s[0] + ORD("0"))); + Out.Char ("."); + FOR i := 1 TO PRINT DO + Out.Char (CHR(s[i] + ORD("0"))); + IF i MOD 64 = 0 THEN + Out.Ln; + Out.Int (i, 5); + Out.String (" ") + END + END; + Out.Ln; + Out.Ln; + In.Ln; + + Console.exit(TRUE) +END exp. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/Windows/Console/fact.ob07 b/programs/develop/oberon07/Samples/Windows/Console/fact.ob07 new file mode 100644 index 000000000..7f059811a --- /dev/null +++ b/programs/develop/oberon07/Samples/Windows/Console/fact.ob07 @@ -0,0 +1,59 @@ +(* + adapted to Oberon-07 by 0CodErr, KolibriOS team + *) +(* + * Written by Andrew Cadach + * + * Recursive (extremely uneficient:-) implementation of factorial + * + * n * (n-1)!, n <> 0 + * By definition, n! = + * 1, n = 0 + * + *) + +MODULE fact; + +IMPORT In, Out, Console; + + +CONST + MAX_INTEGER = ROR(-2, 1); + + +VAR + i, r: INTEGER; + + +PROCEDURE f (n: INTEGER): INTEGER; +VAR + Res: INTEGER; + +BEGIN + IF n = 0 THEN + Res := 1 + ELSE + Res := n * f (n - 1) + END + + RETURN Res +END f; + + +BEGIN + Console.open; + + i := 0; + REPEAT + r := f(i); + Out.String ("The factorial of "); + Out.Int (i, 2); + Out.String (" is "); + Out.Int (r, 0); + Out.Ln; + INC(i) + UNTIL r >= MAX_INTEGER DIV i; + In.Ln; + + Console.exit(TRUE) +END fact. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/Windows/Console/hailst.ob07 b/programs/develop/oberon07/Samples/Windows/Console/hailst.ob07 new file mode 100644 index 000000000..ebe93f3da --- /dev/null +++ b/programs/develop/oberon07/Samples/Windows/Console/hailst.ob07 @@ -0,0 +1,117 @@ +(* + adapted to Oberon-07 by 0CodErr, KolibriOS team + *) +(* + The Hailstone sequence of numbers can be generated + from a starting positive integer, n by: + IF n is 1 THEN the sequence ends. + IF n is even THEN the next n of the sequence = n / 2 + IF n is odd THEN the next n of the sequence = (3 * n) + 1 + The (unproven) Collatz conjecture is that the hailstone sequence + for any starting number always terminates. +*) + +MODULE hailst; + +IMPORT In, Out, API, Console; + + +CONST + maxCard = ROR(-2, 1) DIV 3; + List = 1; + Count = 2; + Max = 3; + + +VAR + a: INTEGER; + + +PROCEDURE HALT(code: INTEGER); +BEGIN + In.Ln; Console.exit(TRUE); API.exit(code) +END HALT; + + +PROCEDURE HailStone(start, _type: INTEGER): INTEGER; +VAR + n, max, count, res: INTEGER; + exit: BOOLEAN; + +BEGIN + count := 1; + n := start; + max := n; + exit := FALSE; + WHILE exit # TRUE DO + IF _type = List THEN + Out.Int (n, 12); + IF count MOD 6 = 0 THEN Out.Ln END + END; + IF n # 1 THEN + IF ODD(n) THEN + IF n < maxCard THEN + n := 3 * n + 1; + IF n > max THEN max := n END + ELSE + Out.String("Exceeding max value for type INTEGER at:"); + Out.Ln; + Out.String("n = "); Out.Int(start, 1); + Out.String(", count = "); Out.Int(count, 1); + Out.String(", intermediate value "); + Out.Int(n, 1); + Out.String(". Aborting."); + Out.Ln; + HALT(2) + END + ELSE + n := n DIV 2 + END; + INC(count) + ELSE + exit := TRUE + END + END; + IF _type = Max THEN res := max ELSE res := count END + + RETURN res +END HailStone; + + +PROCEDURE FindMax(num: INTEGER); +VAR + val, maxCount, maxVal, cnt: INTEGER; + +BEGIN + maxCount := 0; + maxVal := 0; + FOR val := 2 TO num DO + cnt := HailStone(val, Count); + IF cnt > maxCount THEN + maxVal := val; + maxCount := cnt + END + END; + Out.String("Longest sequence below "); Out.Int(num, 1); + Out.String(" is "); Out.Int(HailStone(maxVal, Count), 1); + Out.String(" for n = "); Out.Int(maxVal, 1); + Out.String(" with an intermediate maximum of "); + Out.Int(HailStone(maxVal, Max), 1); + Out.Ln +END FindMax; + + +BEGIN + Console.open; + + a := HailStone(27, List); + Out.Ln; + Out.String("Iterations total = "); Out.Int(HailStone(27, Count), 1); + Out.String(" max value = "); Out.Int(HailStone(27, Max), 1); + Out.Ln; + FindMax(100000); + Out.String("Done."); + Out.Ln; In.Ln; + + Console.exit(TRUE) +END hailst. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/Windows/Console/postfix.ob07 b/programs/develop/oberon07/Samples/Windows/Console/postfix.ob07 new file mode 100644 index 000000000..309011d06 --- /dev/null +++ b/programs/develop/oberon07/Samples/Windows/Console/postfix.ob07 @@ -0,0 +1,123 @@ +(* + adapted to Oberon-07 by 0CodErr, KolibriOS team + *) +(* Example program from Programming In Modula-2, N. Wirth., pg. 56, *) +(* - no WINDOWS in this example *) + +(* this program translates a small language into postfix form + * the language is + * + * expression = term { [ "+" | "-" ] term } + * + * term = factor { [ "*" | "/" ] factor } + * + * factor = letter | "(" expression ")" + * + * letter = "a" | 'b" | … | "z" + * + * try as input + * a+b + * a*b+c + * a+b*c + * a*(b/(c-d)) + *) + +MODULE postfix; + +IMPORT In, Out, Console; + + +CONST + OUT_LINE_SIZE = 80; + IN_LINE_SIZE = 80; + + +VAR + ch : CHAR; + i, index : INTEGER; + out_line : ARRAY OUT_LINE_SIZE OF CHAR; + in_line : ARRAY IN_LINE_SIZE OF CHAR; + cur_ch : INTEGER; + + +PROCEDURE NextChar(): CHAR; +BEGIN + INC(cur_ch) + RETURN in_line[cur_ch - 1] +END NextChar; + + +PROCEDURE expression; +VAR + addop :CHAR; + + + PROCEDURE term; + VAR + mulop :CHAR; + + + PROCEDURE factor; + BEGIN (* factor *) + IF ch = "(" THEN + ch := NextChar(); + expression; + WHILE ch # ")" DO + ch := NextChar() + END (* WHILE *) + ELSE + WHILE (ch < "a") OR (ch > "z") DO + ch := NextChar() + END; (* WHILE *) + out_line[index] := ch; + index := index + 1 + END; (* IF *) + ch := NextChar() + END factor; + + + BEGIN (* term *) + factor; + WHILE (ch = "*") OR (ch = "/") DO + mulop := ch; + ch := NextChar(); + factor; + out_line[index] := mulop; + index := index + 1 + END (* WHILE *) + END term; + + +BEGIN (* expression *) + term; + WHILE (ch = "+") OR (ch = "-") DO + addop := ch; + ch := NextChar(); + term; + out_line[index] := addop; + index := index + 1 + END (* WHILE *) +END expression; + + +BEGIN (* Postfix *) + Console.open; + + index := 1; cur_ch := 0; + Out.String("Enter expression:"); + In.String(in_line); + ch := NextChar(); + WHILE ch > " " DO + expression; + FOR i := 1 TO index - 1 DO + Out.Char(out_line[i]) + END; (* FOR *) + Out.Ln; + index := 1; cur_ch := 0; + Out.String("Enter expression:"); + In.String(in_line); + ch := NextChar() + END; (* WHILE *) + + Console.exit(TRUE) +END postfix. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/Windows/Console/sequence012.ob07 b/programs/develop/oberon07/Samples/Windows/Console/sequence012.ob07 new file mode 100644 index 000000000..782b26708 --- /dev/null +++ b/programs/develop/oberon07/Samples/Windows/Console/sequence012.ob07 @@ -0,0 +1,79 @@ +(* + adapted to Oberon-07 by 0CodErr, KolibriOS team + *) +(* Find sequence of digits 0, 1, 2 and of lengths 1 ... 90, such + that they contain no two adjacent subsequences that are equal *) + +MODULE sequence012; + +IMPORT In, Out, Console; + + +CONST + maxlength = 75; + + +VAR + n: INTEGER; + good: BOOLEAN; + s: ARRAY maxlength OF INTEGER; + + +PROCEDURE printsequence; +VAR + k: INTEGER; +BEGIN + Out.Char(" "); + FOR k := 1 TO n DO Out.Int(s[k], 1) END; + Out.Ln +END printsequence; + + +PROCEDURE changesequence; +BEGIN + IF s[n] = 3 THEN + DEC(n); + changesequence + ELSE + s[n] := s[n] + 1 + END +END changesequence; + + +PROCEDURE try; +VAR + i, l, nhalf: INTEGER; + +BEGIN + IF n <= 1 THEN + good := TRUE + ELSE + l := 0; nhalf := n DIV 2; + REPEAT + INC(l); i := 0; + REPEAT + good := s[n - i] # s[n - l - i]; + INC(i) + UNTIL good OR (i = l) + UNTIL ~good OR (l >= nhalf) + END +END try; + + +BEGIN + Console.open; + + n := 0; + REPEAT + INC(n); + s[n] := 1; try; + WHILE ~good DO + changesequence; + try + END; + printsequence + UNTIL n >= maxlength - 1; + In.Ln; + + Console.exit(TRUE) +END sequence012. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/AMD64.ob07 b/programs/develop/oberon07/Source/AMD64.ob07 index a4ae7285c..899b7e953 100644 --- a/programs/develop/oberon07/Source/AMD64.ob07 +++ b/programs/develop/oberon07/Source/AMD64.ob07 @@ -8,7 +8,7 @@ MODULE AMD64; IMPORT IL, BIN, WR := WRITER, CHL := CHUNKLISTS, LISTS, PATHS, PROG, TARGETS, - REG, C := CONSOLE, UTILS, S := STRINGS, PE32, ELF, X86; + REG, UTILS, S := STRINGS, PE32, ELF, X86, ERRORS; CONST @@ -19,14 +19,16 @@ CONST rcx = REG.R1; rdx = REG.R2; - r8 = REG.R8; - r9 = REG.R9; + r8 = REG.R8; + r9 = REG.R9; rsp = 4; rbp = 5; rsi = 6; rdi = 7; + MAX_XMM = 5; + je = 84H; jne = 85H; jl = 8CH; jge = 8DH; jle = 8EH; jg = 8FH; jb = 82H; sete = 94H; setne = 95H; setl = 9CH; setge = 9DH; setle = 9EH; setg = 9FH; setc = 92H; setnc = 93H; @@ -38,6 +40,8 @@ CONST sBSS = BIN.PICBSS; sIMP = BIN.PICIMP; + FPR_ERR = 41; + TYPE @@ -65,6 +69,10 @@ VAR Win64RegPar: ARRAY 4 OF INTEGER; SystemVRegPar: ARRAY 6 OF INTEGER; + Xmm: ARRAY 1000 OF INTEGER; + + fname: PATHS.PATH; + PROCEDURE OutByte (b: BYTE); BEGIN @@ -96,24 +104,19 @@ BEGIN END OutInt; -PROCEDURE isByte (n: INTEGER): BOOLEAN; - RETURN (-128 <= n) & (n <= 127) -END isByte; - - PROCEDURE short (n: INTEGER): INTEGER; - RETURN 2 * ORD(isByte(n)) + RETURN 2 * ORD(X86.isByte(n)) END short; PROCEDURE long (n: INTEGER): INTEGER; - RETURN 40H * ORD(~isByte(n)) + RETURN 40H * ORD(~X86.isByte(n)) END long; PROCEDURE OutIntByte (n: INTEGER); BEGIN - IF isByte(n) THEN + IF X86.isByte(n) THEN OutByte(n MOD 256) ELSE OutInt(n) @@ -191,10 +194,10 @@ BEGIN END and; -PROCEDURE or (reg1, reg2: INTEGER); (* or reg1, reg2 *) +PROCEDURE _or (reg1, reg2: INTEGER); (* or reg1, reg2 *) BEGIN oprr(09H, reg1, reg2) -END or; +END _or; PROCEDURE add (reg1, reg2: INTEGER); (* add reg1, reg2 *) @@ -211,7 +214,12 @@ END sub; PROCEDURE xchg (reg1, reg2: INTEGER); (* xchg reg1, reg2 *) BEGIN - oprr(87H, reg1, reg2) + IF rax IN {reg1, reg2} THEN + Rex(reg1 + reg2, 0); + OutByte(90H + (reg1 + reg2) MOD 8) + ELSE + oprr(87H, reg1, reg2) + END END xchg; @@ -270,17 +278,9 @@ END GetVarReg; PROCEDURE callimp (label: INTEGER); -VAR - reg: INTEGER; - BEGIN - reg := GetAnyReg(); - lea(reg, label, sIMP); - IF reg >= 8 THEN (* call qword[reg] *) - OutByte(41H) - END; - OutByte2(0FFH, 10H + reg MOD 8); - drop + OutByte2(0FFH, 15H); (* call qword[rip + label + IMP] *) + X86.Reloc(sIMP, label) END callimp; @@ -383,8 +383,7 @@ BEGIN oprlongc(reg, n, oprr) ELSE Rex(reg, 0); - OutByte2(81H + short(n), op + reg MOD 8); - OutIntByte(n) + X86.oprc(op, reg, n) END END oprc; @@ -419,7 +418,7 @@ END andrc; PROCEDURE orrc (reg, n: INTEGER); (* or reg, n *) BEGIN - oprc(0C8H, reg, n, or) + oprc(0C8H, reg, n, _or) END orrc; @@ -440,7 +439,7 @@ BEGIN push(reg2); drop ELSE - OutByte(68H + short(n)); OutIntByte(n) (* push n *) + X86.pushc(n) END END pushc; @@ -553,21 +552,6 @@ BEGIN END jcc; -PROCEDURE jmp (label: INTEGER); (* jmp label *) -BEGIN - X86.jmp(label) -END jmp; - - -PROCEDURE setcc (cc, reg: INTEGER); (* setcc reg8 *) -BEGIN - IF reg >= 8 THEN - OutByte(41H) - END; - OutByte3(0FH, cc, 0C0H + reg MOD 8) -END setcc; - - PROCEDURE shiftrc (op, reg, n: INTEGER); BEGIN Rex(reg, 0); @@ -829,7 +813,7 @@ BEGIN cc := setnc END; OutByte2(7AH, 3 + reg DIV 8); (* jp L *) - setcc(cc, reg); + X86.setcc(cc, reg) (* L: *) END fcmp; @@ -859,7 +843,7 @@ BEGIN CASE opcode OF |IL.opJMP: - jmp(param1) + X86.jmp(param1) |IL.opCALL, IL.opWIN64CALL, IL.opSYSVCALL: REG.Store(R); @@ -907,24 +891,24 @@ BEGIN |IL.opONERR: pushc(param2); - jmp(param1) + X86.jmp(param1) |IL.opPUSHC: pushc(param2) |IL.opPRECALL: - n := param2; - IF (param1 # 0) & (n # 0) THEN + PushAll(0); + IF (param2 # 0) & (xmm >= 0) THEN subrc(rsp, 8) END; - WHILE n > 0 DO + INC(Xmm[0]); + Xmm[Xmm[0]] := xmm + 1; + WHILE xmm >= 0 DO subrc(rsp, 8); movsdmr(rsp, 0, xmm); - DEC(xmm); - DEC(n) + DEC(xmm) END; - ASSERT(xmm = -1); - PushAll(0) + ASSERT(xmm = -1) |IL.opWIN64ALIGN16: ASSERT(rax IN R.regs); @@ -942,14 +926,24 @@ BEGIN push(rax) END - |IL.opRESF: + |IL.opRESF, IL.opRES: + ASSERT(R.top = -1); ASSERT(xmm = -1); - INC(xmm); - n := param2; - IF n > 0 THEN - movsdmr(rsp, n * 8, xmm); - DEC(xmm); - INC(n) + n := Xmm[Xmm[0]]; DEC(Xmm[0]); + + IF opcode = IL.opRESF THEN + INC(xmm); + IF n > 0 THEN + movsdmr(rsp, n * 8, 0); + DEC(xmm); + INC(n) + END; + + IF xmm + n > MAX_XMM THEN + ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR) + END + ELSE + GetRegA END; WHILE n > 0 DO @@ -959,17 +953,6 @@ BEGIN DEC(n) END - |IL.opRES: - ASSERT(R.top = -1); - GetRegA; - n := param2; - WHILE n > 0 DO - INC(xmm); - movsdrm(xmm, rsp, 0); - addrc(rsp, 8); - DEC(n) - END - |IL.opENTER: ASSERT(R.top = -1); @@ -1137,31 +1120,29 @@ BEGIN IF reg2 # -1 THEN mov(reg1, reg2) ELSE - n := param2 * 8; - xor(reg1, reg1); - movrm32(reg1, rbp, n) - END + movrm32(reg1, rbp, param2 * 8) + END; + shiftrc(shl, reg1, 32); + shiftrc(shr, reg1, 32) |IL.opGLOAD64: reg1 := GetAnyReg(); - lea(reg1, param2, sBSS); - movrm(reg1, reg1, 0) + Rex(0, reg1); (* mov reg1, qword[rip + param2 + BSS] *) + OutByte2(8BH, 05H + 8 * (reg1 MOD 8)); + X86.Reloc(sBSS, param2) - |IL.opGLOAD8: + |IL.opGLOAD8, IL.opGLOAD16: reg1 := GetAnyReg(); - lea(reg1, param2, sBSS); - movzx(reg1, reg1, 0, FALSE) - - |IL.opGLOAD16: - reg1 := GetAnyReg(); - lea(reg1, param2, sBSS); - movzx(reg1, reg1, 0, TRUE) + Rex(0, reg1); (* movzx reg1, byte/word[rip + param2 + BSS] *) + OutByte3(0FH, 0B6H + ORD(opcode = IL.opGLOAD16), 05H + 8 * (reg1 MOD 8)); + X86.Reloc(sBSS, param2) |IL.opGLOAD32: reg1 := GetAnyReg(); - xor(reg1, reg1); lea(reg1, param2, sBSS); - movrm32(reg1, reg1, 0) + movrm32(reg1, reg1, 0); + shiftrc(shl, reg1, 32); + shiftrc(shr, reg1, 32) |IL.opVLOAD64: reg1 := GetAnyReg(); @@ -1177,23 +1158,32 @@ BEGIN |IL.opVLOAD32: reg1 := GetAnyReg(); reg2 := GetAnyReg(); - xor(reg1, reg1); movrm(reg2, rbp, param2 * 8); movrm32(reg1, reg2, 0); + shiftrc(shl, reg1, 32); + shiftrc(shr, reg1, 32); drop |IL.opLADR: n := param2 * 8; next := cmd.next(COMMAND); IF (next.opcode = IL.opSAVEF) OR (next.opcode = IL.opSAVEFI) THEN + ASSERT(xmm >= 0); movsdmr(rbp, n, xmm); DEC(xmm); cmd := next ELSIF next.opcode = IL.opLOADF THEN INC(xmm); + IF xmm > MAX_XMM THEN + ERRORS.ErrorMsg(fname, next.param1, next.param2, FPR_ERR) + END; movsdrm(xmm, rbp, n); cmd := next ELSE + IF (next.opcode = IL.opADDC) & ~isLong(n + next.param2) THEN + INC(n, next.param2); + cmd := next + END; reg1 := GetAnyReg(); Rex(0, reg1); OutByte2(8DH, 45H + long(n) + (reg1 MOD 8) * 8); (* lea reg1, qword[rbp+n] *) @@ -1201,6 +1191,11 @@ BEGIN END |IL.opGADR: + next := cmd.next(COMMAND); + IF (next.opcode = IL.opADDC) & ~isLong(param2 + next.param2) THEN + INC(param2, next.param2); + cmd := next + END; lea(GetAnyReg(), param2, sBSS) |IL.opVADR: @@ -1311,15 +1306,15 @@ BEGIN cc := X86.cond(opcode); next := cmd.next(COMMAND); - IF next.opcode = IL.opJE THEN + IF next.opcode = IL.opJNZ THEN jcc(cc, next.param1); cmd := next - ELSIF next.opcode = IL.opJNE THEN + ELSIF next.opcode = IL.opJZ THEN jcc(X86.inv0(cc), next.param1); cmd := next ELSE reg1 := GetAnyReg(); - setcc(cc + 16, reg1); + X86.setcc(cc + 16, reg1); andrc(reg1, 1) END @@ -1342,36 +1337,23 @@ BEGIN PushAll(n) END - |IL.opACC: - IF (R.top # 0) OR (R.stk[0] # rax) THEN - PushAll(0); - GetRegA; - pop(rax); - DEC(R.pushed) - END - - |IL.opJNZ: + |IL.opJNZ1: UnOp(reg1); test(reg1); jcc(jne, param1) - |IL.opJZ: - UnOp(reg1); - test(reg1); - jcc(je, param1) - |IL.opJG: UnOp(reg1); test(reg1); jcc(jg, param1) - |IL.opJE: + |IL.opJNZ: UnOp(reg1); test(reg1); jcc(jne, param1); drop - |IL.opJNE: + |IL.opJZ: UnOp(reg1); test(reg1); jcc(je, param1); @@ -1388,11 +1370,11 @@ BEGIN cmprc(reg1, 64); jcc(jb, L); xor(reg1, reg1); - jmp(label); + X86.jmp(label); X86.SetLabel(L); Rex(reg2, reg1); OutByte3(0FH, 0A3H, 0C0H + 8 * (reg1 MOD 8) + reg2 MOD 8); (* bt reg2, reg1 *) - setcc(setc, reg1); + X86.setcc(setc, reg1); andrc(reg1, 1); X86.SetLabel(label); drop @@ -1402,19 +1384,19 @@ BEGIN Rex(reg1, 0); OutByte2(0FH, 0BAH); (* bt reg1, param2 *) OutByte2(0E0H + reg1 MOD 8, param2); - setcc(setc, reg1); + X86.setcc(setc, reg1); andrc(reg1, 1) |IL.opNOT: UnOp(reg1); test(reg1); - setcc(sete, reg1); + X86.setcc(sete, reg1); andrc(reg1, 1) |IL.opORD: UnOp(reg1); test(reg1); - setcc(setne, reg1); + X86.setcc(setne, reg1); andrc(reg1, 1) |IL.opABS: @@ -1439,9 +1421,9 @@ BEGIN X86.SetLabel(label); cmprr(reg1, reg2); IF opcode = IL.opEQB THEN - setcc(sete, reg1) + X86.setcc(sete, reg1) ELSE - setcc(setne, reg1) + X86.setcc(setne, reg1) END; andrc(reg1, 1) @@ -1453,7 +1435,7 @@ BEGIN UnOp(reg1); xorrc(reg1, param2) - |IL.opADDSL, IL.opADDSR: + |IL.opADDSC: UnOp(reg1); orrc(reg1, param2) @@ -1688,19 +1670,18 @@ BEGIN |IL.opSUBR, IL.opSUBL: UnOp(reg1); - n := param2; - IF n = 1 THEN + IF param2 = 1 THEN decr(reg1) - ELSIF n = -1 THEN + ELSIF param2 = -1 THEN incr(reg1) - ELSIF n # 0 THEN - subrc(reg1, n) + ELSIF param2 # 0 THEN + subrc(reg1, param2) END; IF opcode = IL.opSUBL THEN neg(reg1) END - |IL.opADDL, IL.opADDR: + |IL.opADDC: IF (param2 # 0) & ~isLong(param2) THEN UnOp(reg1); next := cmd.next(COMMAND); @@ -1851,7 +1832,7 @@ BEGIN |IL.opADDS: BinOp(reg1, reg2); - or(reg1, reg2); + _or(reg1, reg2); drop |IL.opSUBS: @@ -1860,7 +1841,7 @@ BEGIN and(reg1, reg2); drop - |IL.opNOP: + |IL.opNOP, IL.opAND, IL.opOR: |IL.opSWITCH: UnOp(reg1); @@ -2008,8 +1989,8 @@ BEGIN reg1 := GetAnyReg(); CASE opcode OF - |IL.opEQP, IL.opEQIP: setcc(sete, reg1) - |IL.opNEP, IL.opNEIP: setcc(setne, reg1) + |IL.opEQP, IL.opEQIP: X86.setcc(sete, reg1) + |IL.opNEP, IL.opNEIP: X86.setcc(setne, reg1) END; andrc(reg1, 1) @@ -2045,9 +2026,8 @@ BEGIN drop |IL.opCLEANUP: - n := param2 * 8; - IF n # 0 THEN - addrc(rsp, n) + IF param2 # 0 THEN + addrc(rsp, param2 * 8) END |IL.opPOPSP: @@ -2056,10 +2036,14 @@ BEGIN |IL.opLOADF: UnOp(reg1); INC(xmm); + IF xmm > MAX_XMM THEN + ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR) + END; movsdrm(xmm, reg1, 0); drop |IL.opPUSHF: + ASSERT(xmm >= 0); subrc(rsp, 8); movsdmr(rsp, 0, xmm); DEC(xmm) @@ -2067,66 +2051,78 @@ BEGIN |IL.opCONSTF: float := cmd.float; INC(xmm); - reg1 := GetAnyReg(); - lea(reg1, Numbers_Offs + Numbers_Count * 8, sDATA); - movsdrm(xmm, reg1, 0); - drop; + IF xmm > MAX_XMM THEN + ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR) + END; + (* movsd xmm, qword ptr [rip + Numbers_Offs + Numbers_Count * 8 + DATA] *) + OutByte(0F2H); + IF xmm >= 8 THEN + OutByte(44H) + END; + OutByte3(0FH, 10H, 05H + 8 * (xmm MOD 8)); + X86.Reloc(sDATA, Numbers_Offs + Numbers_Count * 8); NewNumber(UTILS.splitf(float, a, b)) |IL.opSAVEF, IL.opSAVEFI: + ASSERT(xmm >= 0); UnOp(reg1); movsdmr(reg1, 0, xmm); DEC(xmm); drop - |IL.opADDF, IL.opADDFI: + |IL.opADDF: + ASSERT(xmm >= 1); opxx(58H, xmm - 1, xmm); DEC(xmm) |IL.opSUBF: + ASSERT(xmm >= 1); opxx(5CH, xmm - 1, xmm); DEC(xmm) |IL.opSUBFI: + ASSERT(xmm >= 1); opxx(5CH, xmm, xmm - 1); opxx(10H, xmm - 1, xmm); DEC(xmm) |IL.opMULF: + ASSERT(xmm >= 1); opxx(59H, xmm - 1, xmm); DEC(xmm) |IL.opDIVF: + ASSERT(xmm >= 1); opxx(5EH, xmm - 1, xmm); DEC(xmm) |IL.opDIVFI: + ASSERT(xmm >= 1); opxx(5EH, xmm, xmm - 1); opxx(10H, xmm - 1, xmm); DEC(xmm) - |IL.opUMINF: - reg1 := GetAnyReg(); - lea(reg1, Numbers_Offs, sDATA); - OutByte3(66H, 40H + reg1 DIV 8 + (xmm DIV 8) * 4, 0FH); (* xorpd xmm, xmmword[reg1] *) - OutByte2(57H, reg1 MOD 8 + (xmm MOD 8) * 8); - drop - - |IL.opFABS: - reg1 := GetAnyReg(); - lea(reg1, Numbers_Offs + 16, sDATA); - OutByte3(66H, 40H + reg1 DIV 8 + (xmm DIV 8) * 4, 0FH); (* andpd xmm, xmmword[reg1] *) - OutByte2(54H, reg1 MOD 8 + (xmm MOD 8) * 8); - drop + |IL.opFABS, IL.opUMINF: (* andpd/xorpd xmm, xmmword[rip + Numbers_Offs + (16) + DATA] *) + ASSERT(xmm >= 0); + OutByte(66H); + IF xmm >= 8 THEN + OutByte(44H) + END; + OutByte3(0FH, 54H + 3 * ORD(opcode = IL.opUMINF), 05H + (xmm MOD 8) * 8); + X86.Reloc(sDATA, Numbers_Offs + 16 * ORD(opcode = IL.opFABS)) |IL.opFLT: UnOp(reg1); INC(xmm); + IF xmm > MAX_XMM THEN + ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR) + END; OutByte(0F2H); Rex(reg1, xmm); OutByte(0FH); (* cvtsi2sd xmm, reg1 *) OutByte2(2AH, 0C0H + (xmm MOD 8) * 8 + reg1 MOD 8); drop |IL.opFLOOR: + ASSERT(xmm >= 0); reg1 := GetAnyReg(); subrc(rsp, 8); OutByte3(00FH, 0AEH, 05CH); OutByte2(024H, 004H); (* stmxcsr dword[rsp+4]; *) @@ -2141,15 +2137,22 @@ BEGIN DEC(xmm) |IL.opEQF .. IL.opGEF: + ASSERT(xmm >= 1); fcmp(opcode, xmm); DEC(xmm, 2) |IL.opINF: INC(xmm); - reg1 := GetAnyReg(); - lea(reg1, Numbers_Offs + 32, sDATA); - movsdrm(xmm, reg1, 0); - drop + IF xmm > MAX_XMM THEN + ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR) + END; + (* movsd xmm, qword ptr [rip + Numbers_Offs + 32 + DATA] *) + OutByte(0F2H); + IF xmm >= 8 THEN + OutByte(44H) + END; + OutByte3(0FH, 10H, 05H + 8 * (xmm MOD 8)); + X86.Reloc(sDATA, Numbers_Offs + 32) |IL.opPACK, IL.opPACKC: IF opcode = IL.opPACK THEN @@ -2175,7 +2178,7 @@ BEGIN and(reg2, reg1); pop(reg1); - or(reg2, reg1); + _or(reg2, reg1); pop(reg1); movmr(reg1, 0, reg2); drop; @@ -2218,7 +2221,7 @@ BEGIN push(reg2); lea(reg2, Numbers_Offs + 48, sDATA); (* {52..61} *) movrm(reg2, reg2, 0); - or(reg1, reg2); + _or(reg1, reg2); pop(reg2); Rex(reg1, 0); @@ -2248,25 +2251,19 @@ BEGIN END |IL.opGLOAD64_PARAM: - reg2 := GetAnyReg(); - lea(reg2, param2, sBSS); - movrm(reg2, reg2, 0); - push(reg2); - drop + OutByte2(0FFH, 35H); (* push qword[rip + param2 + BSS] *) + X86.Reloc(sBSS, param2) |IL.opCONST_PARAM: pushc(param2) - |IL.opGLOAD32_PARAM: - reg1 := GetAnyReg(); - xor(reg1, reg1); - lea(reg1, param2, sBSS); - movrm32(reg1, reg1, 0); - push(reg1); - drop - - |IL.opLOAD32_PARAM: - UnOp(reg1); + |IL.opGLOAD32_PARAM, IL.opLOAD32_PARAM: + IF opcode = IL.opGLOAD32_PARAM THEN + reg1 := GetAnyReg(); + lea(reg1, param2, sBSS) + ELSE + UnOp(reg1) + END; movrm32(reg1, reg1, 0); shiftrc(shl, reg1, 32); shiftrc(shr, reg1, 32); @@ -2275,13 +2272,14 @@ BEGIN |IL.opLLOAD32_PARAM: reg1 := GetAnyReg(); - xor(reg1, reg1); reg2 := GetVarReg(param2); IF reg2 # -1 THEN mov(reg1, reg2) ELSE movrm32(reg1, rbp, param2 * 8) END; + shiftrc(shl, reg1, 32); + shiftrc(shr, reg1, 32); push(reg1); drop @@ -2313,12 +2311,10 @@ BEGIN drop; drop ELSE - reg2 := GetAnyReg(); - lea(reg2, param1, sBSS); - Rex(reg2, 0); - OutByte2(0C7H, reg2 MOD 8); (* mov qword[reg2], param2 *) - OutInt(param2); - drop + (* mov qword[rip + param1 - 4 + BSS], param2 *) + OutByte3(48H, 0C7H, 05H); + X86.Reloc(sBSS, param1 - 4); + OutInt(param2) END |IL.opLADR_SAVE: @@ -2431,7 +2427,7 @@ BEGIN oprr2(0FH, 0ABH + 8 * ORD(opcode = IL.opLADR_EXCL), reg2, reg1) (* bts/btr reg2, reg1 *) ELSE n := param2 * 8; - OutByte2(73H, 5 + 3 * ORD(~isByte(n))); (* jnb L *) + OutByte2(73H, 5 + 3 * ORD(~X86.isByte(n))); (* jnb L *) Rex(0, reg1); OutByte3(0FH, 0ABH + 8 * ORD(opcode = IL.opLADR_EXCL), 45H + long(n) + 8 * (reg1 MOD 8)); OutIntByte(n) (* bts/btr qword[rbp+n], reg1 *) @@ -2453,6 +2449,9 @@ BEGIN OutByte(param2) END + |IL.opFNAME: + fname := cmd(IL.FNAMECMD).fname + |IL.opLOOP, IL.opENDLOOP: END; @@ -2485,10 +2484,9 @@ BEGIN push(rcx); CallRTL(IL._dllentry); test(rax); - jcc(je, dllret) - END; - - IF target = TARGETS.Linux64 THEN + jcc(je, dllret); + pushc(0) + ELSIF target = TARGETS.Linux64 THEN push(rsp) ELSE pushc(0) @@ -2527,7 +2525,7 @@ VAR exp: IL.EXPORT_PROC; - PROCEDURE import (imp: LISTS.LIST); + PROCEDURE _import (imp: LISTS.LIST); VAR lib: IL.IMPORT_LIB; proc: IL.IMPORT_PROC; @@ -2545,7 +2543,7 @@ VAR lib := lib.next(IL.IMPORT_LIB) END - END import; + END _import; BEGIN @@ -2598,7 +2596,7 @@ BEGIN exp := exp.next(IL.EXPORT_PROC) END; - import(IL.codes.import) + _import(IL.codes._import) END epilog; @@ -2631,6 +2629,7 @@ VAR path, modname, ext: PATHS.PATH; BEGIN + Xmm[0] := 0; tcount := CHL.Length(IL.codes.types); Win64RegPar[0] := rcx; diff --git a/programs/develop/oberon07/Source/ARITH.ob07 b/programs/develop/oberon07/Source/ARITH.ob07 index 2b10af2e1..28b766863 100644 --- a/programs/develop/oberon07/Source/ARITH.ob07 +++ b/programs/develop/oberon07/Source/ARITH.ob07 @@ -16,11 +16,12 @@ CONST tBOOLEAN* = 4; tCHAR* = 5; tWCHAR* = 6; tSTRING* = 7; + opEQ* = 0; opNE* = 1; opLT* = 2; opLE* = 3; opGT* = 4; opGE* = 5; + opIN* = 6; opIS* = 7; + TYPE - RELATION* = ARRAY 3 OF CHAR; - VALUE* = RECORD typ*: INTEGER; @@ -672,7 +673,7 @@ BEGIN END equal; -PROCEDURE relation* (VAR v: VALUE; v2: VALUE; operator: RELATION; VAR error: INTEGER); +PROCEDURE relation* (VAR v: VALUE; v2: VALUE; op: INTEGER; VAR error: INTEGER); VAR res: BOOLEAN; @@ -681,36 +682,34 @@ BEGIN res := FALSE; - CASE operator[0] OF + CASE op OF - |"=": + |opEQ: res := equal(v, v2, error) - |"#": + |opNE: res := ~equal(v, v2, error) - |"<": - IF operator[1] = "=" THEN - res := less(v, v2, error); - IF error = 0 THEN - res := equal(v, v2, error) OR res - END - ELSE - res := less(v, v2, error) + |opLT: + res := less(v, v2, error) + + |opLE: + res := less(v, v2, error); + IF error = 0 THEN + res := equal(v, v2, error) OR res END - |">": - IF operator[1] = "=" THEN - res := ~less(v, v2, error) - ELSE - res := less(v, v2, error); - IF error = 0 THEN - res := equal(v, v2, error) OR res - END; - res := ~res - END + |opGE: + res := ~less(v, v2, error) - |"I": + |opGT: + res := less(v, v2, error); + IF error = 0 THEN + res := equal(v, v2, error) OR res + END; + res := ~res + + |opIN: IF (v.typ = tINTEGER) & (v2.typ = tSET) THEN IF range(v, 0, UTILS.target.maxSet) THEN res := v.int IN v2.set @@ -762,6 +761,20 @@ BEGIN END setInt; +PROCEDURE concat* (VAR s: ARRAY OF CHAR; s1: ARRAY OF CHAR): BOOLEAN; +VAR + res: BOOLEAN; + +BEGIN + res := LENGTH(s) + LENGTH(s1) < LEN(s); + IF res THEN + STRINGS.append(s, s1) + END + + RETURN res +END concat; + + PROCEDURE init; VAR i: INTEGER; diff --git a/programs/develop/oberon07/Source/BIN.ob07 b/programs/develop/oberon07/Source/BIN.ob07 index 14c94bc8b..d7fe3334a 100644 --- a/programs/develop/oberon07/Source/BIN.ob07 +++ b/programs/develop/oberon07/Source/BIN.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018-2019, Anton Krotov + Copyright (c) 2018-2020, Anton Krotov All rights reserved. *) @@ -56,7 +56,7 @@ TYPE vmajor*, vminor*: WCHAR; modname*: INTEGER; - import*: CHL.BYTELIST; + _import*: CHL.BYTELIST; export*: CHL.BYTELIST; rel_list*: LISTS.LIST; imp_list*: LISTS.LIST; @@ -84,10 +84,10 @@ BEGIN program.imp_list := LISTS.create(NIL); program.exp_list := LISTS.create(NIL); - program.data := CHL.CreateByteList(); - program.code := CHL.CreateByteList(); - program.import := CHL.CreateByteList(); - program.export := CHL.CreateByteList() + program.data := CHL.CreateByteList(); + program.code := CHL.CreateByteList(); + program._import := CHL.CreateByteList(); + program.export := CHL.CreateByteList() RETURN program END create; @@ -120,7 +120,7 @@ BEGIN END PutData; -PROCEDURE get32le* (array: CHL.BYTELIST; idx: INTEGER): INTEGER; +PROCEDURE get32le* (_array: CHL.BYTELIST; idx: INTEGER): INTEGER; VAR i: INTEGER; x: INTEGER; @@ -129,7 +129,7 @@ BEGIN x := 0; FOR i := 3 TO 0 BY -1 DO - x := LSL(x, 8) + CHL.GetByte(array, idx + i) + x := LSL(x, 8) + CHL.GetByte(_array, idx + i) END; IF UTILS.bit_depth = 64 THEN @@ -143,13 +143,13 @@ BEGIN END get32le; -PROCEDURE put32le* (array: CHL.BYTELIST; idx: INTEGER; x: INTEGER); +PROCEDURE put32le* (_array: CHL.BYTELIST; idx: INTEGER; x: INTEGER); VAR i: INTEGER; BEGIN FOR i := 0 TO 3 DO - CHL.SetByte(array, idx + i, UTILS.Byte(x, i)) + CHL.SetByte(_array, idx + i, UTILS.Byte(x, i)) END END put32le; @@ -224,15 +224,15 @@ VAR imp: IMPRT; BEGIN - CHL.PushByte(program.import, 0); - CHL.PushByte(program.import, 0); + CHL.PushByte(program._import, 0); + CHL.PushByte(program._import, 0); - IF ODD(CHL.Length(program.import)) THEN - CHL.PushByte(program.import, 0) + IF ODD(CHL.Length(program._import)) THEN + CHL.PushByte(program._import, 0) END; NEW(imp); - imp.nameoffs := CHL.PushStr(program.import, name); + imp.nameoffs := CHL.PushStr(program._import, name); imp.label := label; LISTS.push(program.imp_list, imp) END Import; @@ -285,19 +285,18 @@ END Export; PROCEDURE GetIProc* (program: PROGRAM; n: INTEGER): IMPRT; VAR - import: IMPRT; - res: IMPRT; + _import, res: IMPRT; BEGIN - import := program.imp_list.first(IMPRT); + _import := program.imp_list.first(IMPRT); res := NIL; - WHILE (import # NIL) & (n >= 0) DO - IF import.label # 0 THEN - res := import; + WHILE (_import # NIL) & (n >= 0) DO + IF _import.label # 0 THEN + res := _import; DEC(n) END; - import := import.next(IMPRT) + _import := _import.next(IMPRT) END; ASSERT(n = -1) @@ -349,7 +348,7 @@ BEGIN END fixup; -PROCEDURE InitArray* (VAR array: ARRAY OF BYTE; VAR idx: INTEGER; hex: ARRAY OF CHAR); +PROCEDURE InitArray* (VAR _array: ARRAY OF BYTE; VAR idx: INTEGER; hex: ARRAY OF CHAR); VAR i, k: INTEGER; @@ -375,7 +374,7 @@ BEGIN k := k DIV 2; FOR i := 0 TO k - 1 DO - array[i + idx] := hexdgt(hex[2 * i]) * 16 + hexdgt(hex[2 * i + 1]) + _array[i + idx] := hexdgt(hex[2 * i]) * 16 + hexdgt(hex[2 * i + 1]) END; INC(idx, k) diff --git a/programs/develop/oberon07/Source/CHUNKLISTS.ob07 b/programs/develop/oberon07/Source/CHUNKLISTS.ob07 index 03b505c2f..548eaf165 100644 --- a/programs/develop/oberon07/Source/CHUNKLISTS.ob07 +++ b/programs/develop/oberon07/Source/CHUNKLISTS.ob07 @@ -153,14 +153,14 @@ BEGIN END GetStr; -PROCEDURE WriteToFile* (file: WR.FILE; list: BYTELIST); +PROCEDURE WriteToFile* (list: BYTELIST); VAR chunk: BYTECHUNK; BEGIN chunk := list.first(BYTECHUNK); WHILE chunk # NIL DO - WR.Write(file, chunk.data, chunk.count); + WR.Write(chunk.data, chunk.count); chunk := chunk.next(BYTECHUNK) END END WriteToFile; diff --git a/programs/develop/oberon07/Source/Compiler.ob07 b/programs/develop/oberon07/Source/Compiler.ob07 index 32b1aebac..664c03f9a 100644 --- a/programs/develop/oberon07/Source/Compiler.ob07 +++ b/programs/develop/oberon07/Source/Compiler.ob07 @@ -8,14 +8,14 @@ MODULE Compiler; IMPORT ST := STATEMENTS, PARS, UTILS, PATHS, PROG, C := CONSOLE, - ERRORS, STRINGS, WRITER, MSP430, THUMB, TARGETS; + ERRORS, STRINGS, WRITER, MSP430, THUMB, TARGETS, SCAN; PROCEDURE keys (VAR options: PROG.OPTIONS; VAR out: PARS.PATH); VAR param: PARS.PATH; i, j: INTEGER; - end: BOOLEAN; + _end: BOOLEAN; value: INTEGER; minor, major: INTEGER; @@ -24,7 +24,7 @@ VAR BEGIN out := ""; checking := options.checking; - end := FALSE; + _end := FALSE; i := 3; REPEAT UTILS.GetArg(i, param); @@ -113,18 +113,26 @@ BEGIN DEC(i) END + ELSIF param = "-lower" THEN + options.lower := TRUE + ELSIF param = "-pic" THEN options.pic := TRUE + ELSIF param = "-def" THEN + INC(i); + UTILS.GetArg(i, param); + SCAN.NewDef(param) + ELSIF param = "" THEN - end := TRUE + _end := TRUE ELSE ERRORS.BadParam(param) END; INC(i) - UNTIL end; + UNTIL _end; options.checking := checking END keys; @@ -165,6 +173,7 @@ BEGIN options.stack := 2; options.version := 65536; options.pic := FALSE; + options.lower := FALSE; options.checking := ST.chkALL; PATHS.GetCurrentDirectory(app_path); @@ -203,6 +212,8 @@ BEGIN C.StringLn(" -stk set size of stack in Mbytes (Windows, Linux, KolibriOS)"); C.Ln; C.StringLn(" -nochk <'ptibcwra'> disable runtime checking (pointers, types, indexes,"); C.StringLn(" BYTE, CHR, WCHR)"); C.Ln; + C.StringLn(" -lower allow lower case for keywords"); C.Ln; + C.StringLn(" -def define conditional compilation symbol"); C.Ln; C.StringLn(" -ver set version of program (KolibriOS DLL)"); C.Ln; C.StringLn(" -ram set size of RAM in bytes (MSP430) or Kbytes (STM32)"); C.Ln; C.StringLn(" -rom set size of ROM in bytes (MSP430) or Kbytes (STM32)"); C.Ln; @@ -226,6 +237,8 @@ BEGIN ERRORS.Error(205) END; + SCAN.NewDef(param); + IF TARGETS.Select(param) THEN target := TARGETS.target ELSE diff --git a/programs/develop/oberon07/Source/ELF.ob07 b/programs/develop/oberon07/Source/ELF.ob07 index df64fcae5..87c688ec6 100644 --- a/programs/develop/oberon07/Source/ELF.ob07 +++ b/programs/develop/oberon07/Source/ELF.ob07 @@ -1,13 +1,13 @@ (* BSD 2-Clause License - Copyright (c) 2019, Anton Krotov + Copyright (c) 2019-2020, Anton Krotov All rights reserved. *) MODULE ELF; -IMPORT BIN, WR := WRITER, CHL := CHUNKLISTS, LISTS; +IMPORT BIN, WR := WRITER, CHL := CHUNKLISTS, LISTS, PE32, UTILS; CONST @@ -85,9 +85,6 @@ TYPE END; - FILE = WR.FILE; - - VAR dynamic: LISTS.LIST; @@ -97,75 +94,38 @@ VAR hashtab, bucket, chain: CHL.INTLIST; -PROCEDURE align (n, _align: INTEGER): INTEGER; +PROCEDURE Write16 (w: WCHAR); BEGIN - IF n MOD _align # 0 THEN - n := n + _align - (n MOD _align) - END - - RETURN n -END align; - - -PROCEDURE Write16 (file: FILE; w: WCHAR); -BEGIN - WR.Write16LE(file, ORD(w)) + WR.Write16LE(ORD(w)) END Write16; -PROCEDURE WritePH (file: FILE; ph: Elf32_Phdr); +PROCEDURE WritePH (ph: Elf32_Phdr); BEGIN - WR.Write32LE(file, ph.p_type); - WR.Write32LE(file, ph.p_offset); - WR.Write32LE(file, ph.p_vaddr); - WR.Write32LE(file, ph.p_paddr); - WR.Write32LE(file, ph.p_filesz); - WR.Write32LE(file, ph.p_memsz); - WR.Write32LE(file, ph.p_flags); - WR.Write32LE(file, ph.p_align) + WR.Write32LE(ph.p_type); + WR.Write32LE(ph.p_offset); + WR.Write32LE(ph.p_vaddr); + WR.Write32LE(ph.p_paddr); + WR.Write32LE(ph.p_filesz); + WR.Write32LE(ph.p_memsz); + WR.Write32LE(ph.p_flags); + WR.Write32LE(ph.p_align) END WritePH; -PROCEDURE WritePH64 (file: FILE; ph: Elf32_Phdr); +PROCEDURE WritePH64 (ph: Elf32_Phdr); BEGIN - WR.Write32LE(file, ph.p_type); - WR.Write32LE(file, ph.p_flags); - WR.Write64LE(file, ph.p_offset); - WR.Write64LE(file, ph.p_vaddr); - WR.Write64LE(file, ph.p_paddr); - WR.Write64LE(file, ph.p_filesz); - WR.Write64LE(file, ph.p_memsz); - WR.Write64LE(file, ph.p_align) + WR.Write32LE(ph.p_type); + WR.Write32LE(ph.p_flags); + WR.Write64LE(ph.p_offset); + WR.Write64LE(ph.p_vaddr); + WR.Write64LE(ph.p_paddr); + WR.Write64LE(ph.p_filesz); + WR.Write64LE(ph.p_memsz); + WR.Write64LE(ph.p_align) END WritePH64; -PROCEDURE fixup (program: BIN.PROGRAM; text, data, bss: INTEGER; amd64: BOOLEAN); -VAR - reloc: BIN.RELOC; - code: CHL.BYTELIST; - L, delta, delta0: INTEGER; - -BEGIN - code := program.code; - delta0 := 3 - 7 * ORD(amd64); - reloc := program.rel_list.first(BIN.RELOC); - - WHILE reloc # NIL DO - - L := BIN.get32le(code, reloc.offset); - delta := delta0 - reloc.offset - text; - - CASE reloc.opcode OF - |BIN.PICDATA: BIN.put32le(code, reloc.offset, L + data + delta) - |BIN.PICCODE: BIN.put32le(code, reloc.offset, BIN.GetLabel(program, L) + text + delta) - |BIN.PICBSS: BIN.put32le(code, reloc.offset, L + bss + delta) - END; - - reloc := reloc.next(BIN.RELOC) - END -END fixup; - - PROCEDURE NewDyn (tag, val: INTEGER); VAR dyn: Elf32_Dyn; @@ -271,13 +231,11 @@ VAR ehdr: Elf32_Ehdr; phdr: ARRAY 16 OF Elf32_Phdr; - i, BaseAdr, offset, pad, VA, symCount: INTEGER; + i, BaseAdr, DynAdr, offset, pad, VA, symCount: INTEGER; SizeOf: RECORD header, code, data, bss: INTEGER END; - Offset: RECORD symtab, reltab, hash, strtab, dyn: INTEGER END; - - File: FILE; + Offset: RECORD symtab, reltab, hash, strtab: INTEGER END; Interpreter: ARRAY 40 OF CHAR; lenInterpreter: INTEGER; @@ -285,6 +243,8 @@ VAR Name: ARRAY 2048 OF CHAR; + Address: PE32.VIRTUAL_ADDR; + BEGIN dynamic := LISTS.create(NIL); symtab := LISTS.create(NIL); @@ -389,8 +349,8 @@ BEGIN symCount := LISTS.count(symtab); - bucket := CHL.CreateIntList(); - chain := CHL.CreateIntList(); + bucket := CHL.CreateIntList(); + chain := CHL.CreateIntList(); FOR i := 1 TO symCount DO CHL.PushInt(bucket, 0); @@ -431,12 +391,12 @@ BEGIN Offset.hash := Offset.reltab + (8 + 16 * ORD(amd64)) * 2; Offset.strtab := Offset.hash + (symCount * 2 + 2) * 4; - Offset.dyn := phdr[dyn].p_offset; + DynAdr := phdr[dyn].p_offset + BaseAdr; - item := LISTS.getidx(dynamic, 1); item(Elf32_Dyn).d_val := Offset.strtab + Offset.dyn + BaseAdr; - item := LISTS.getidx(dynamic, 3); item(Elf32_Dyn).d_val := Offset.symtab + Offset.dyn + BaseAdr; - item := LISTS.getidx(dynamic, 5); item(Elf32_Dyn).d_val := Offset.reltab + Offset.dyn + BaseAdr; - item := LISTS.getidx(dynamic, 8); item(Elf32_Dyn).d_val := Offset.hash + Offset.dyn + BaseAdr; + item := LISTS.getidx(dynamic, 1); item(Elf32_Dyn).d_val := Offset.strtab + DynAdr; + item := LISTS.getidx(dynamic, 3); item(Elf32_Dyn).d_val := Offset.symtab + DynAdr; + item := LISTS.getidx(dynamic, 5); item(Elf32_Dyn).d_val := Offset.reltab + DynAdr; + item := LISTS.getidx(dynamic, 8); item(Elf32_Dyn).d_val := Offset.hash + DynAdr; phdr[dyn].p_filesz := Offset.strtab + CHL.Length(strtab) + 8 + 8 * ORD(amd64); phdr[dyn].p_memsz := phdr[dyn].p_filesz; @@ -450,12 +410,12 @@ BEGIN phdr[header].p_offset := offset; phdr[header].p_vaddr := BaseAdr; phdr[header].p_paddr := BaseAdr; - phdr[header].p_filesz := 244 + 156 * ORD(amd64) + lenInterpreter + phdr[dyn].p_filesz; + phdr[header].p_filesz := SizeOf.header + lenInterpreter + phdr[dyn].p_filesz; phdr[header].p_memsz := phdr[header].p_filesz; phdr[header].p_flags := PF_R + PF_W; phdr[header].p_align := 1000H; - offset := offset + phdr[header].p_filesz; + INC(offset, phdr[header].p_filesz); VA := BaseAdr + offset + 1000H; phdr[text].p_type := 1; @@ -469,7 +429,7 @@ BEGIN ehdr.e_entry := phdr[text].p_vaddr; - offset := offset + phdr[text].p_filesz; + INC(offset, phdr[text].p_filesz); VA := BaseAdr + offset + 2000H; pad := (16 - VA MOD 16) MOD 16; @@ -482,7 +442,7 @@ BEGIN phdr[data].p_flags := PF_R + PF_W; phdr[data].p_align := 1000H; - offset := offset + phdr[data].p_filesz; + INC(offset, phdr[data].p_filesz); VA := BaseAdr + offset + 3000H; phdr[bss].p_type := 1; @@ -494,7 +454,12 @@ BEGIN phdr[bss].p_flags := PF_R + PF_W; phdr[bss].p_align := 1000H; - fixup(program, ehdr.e_entry, phdr[data].p_vaddr + pad, align(phdr[bss].p_vaddr, 16), amd64); + Address.Code := ehdr.e_entry; + Address.Data := phdr[data].p_vaddr + pad; + Address.Bss := WR.align(phdr[bss].p_vaddr, 16); + Address.Import := 0; + + PE32.fixup(program, Address, amd64); item := symtab.first; WHILE item # NIL DO @@ -509,146 +474,137 @@ BEGIN item := LISTS.getidx(dynamic, 11); item(Elf32_Dyn).d_val := BIN.GetLabel(program, fini) + ehdr.e_entry END; - File := WR.Create(FileName); + WR.Create(FileName); FOR i := 0 TO EI_NIDENT - 1 DO - WR.WriteByte(File, ehdr.e_ident[i]) + WR.WriteByte(ehdr.e_ident[i]) END; - Write16(File, ehdr.e_type); - Write16(File, ehdr.e_machine); + Write16(ehdr.e_type); + Write16(ehdr.e_machine); - WR.Write32LE(File, ehdr.e_version); + WR.Write32LE(ehdr.e_version); IF amd64 THEN - WR.Write64LE(File, ehdr.e_entry); - WR.Write64LE(File, ehdr.e_phoff); - WR.Write64LE(File, ehdr.e_shoff) + WR.Write64LE(ehdr.e_entry); + WR.Write64LE(ehdr.e_phoff); + WR.Write64LE(ehdr.e_shoff) ELSE - WR.Write32LE(File, ehdr.e_entry); - WR.Write32LE(File, ehdr.e_phoff); - WR.Write32LE(File, ehdr.e_shoff) + WR.Write32LE(ehdr.e_entry); + WR.Write32LE(ehdr.e_phoff); + WR.Write32LE(ehdr.e_shoff) END; - WR.Write32LE(File, ehdr.e_flags); + WR.Write32LE(ehdr.e_flags); - Write16(File, ehdr.e_ehsize); - Write16(File, ehdr.e_phentsize); - Write16(File, ehdr.e_phnum); - Write16(File, ehdr.e_shentsize); - Write16(File, ehdr.e_shnum); - Write16(File, ehdr.e_shstrndx); + Write16(ehdr.e_ehsize); + Write16(ehdr.e_phentsize); + Write16(ehdr.e_phnum); + Write16(ehdr.e_shentsize); + Write16(ehdr.e_shnum); + Write16(ehdr.e_shstrndx); IF amd64 THEN - WritePH64(File, phdr[interp]); - WritePH64(File, phdr[dyn]); - WritePH64(File, phdr[header]); - WritePH64(File, phdr[text]); - WritePH64(File, phdr[data]); - WritePH64(File, phdr[bss]) + WritePH64(phdr[interp]); + WritePH64(phdr[dyn]); + WritePH64(phdr[header]); + WritePH64(phdr[text]); + WritePH64(phdr[data]); + WritePH64(phdr[bss]) ELSE - WritePH(File, phdr[interp]); - WritePH(File, phdr[dyn]); - WritePH(File, phdr[header]); - WritePH(File, phdr[text]); - WritePH(File, phdr[data]); - WritePH(File, phdr[bss]) + WritePH(phdr[interp]); + WritePH(phdr[dyn]); + WritePH(phdr[header]); + WritePH(phdr[text]); + WritePH(phdr[data]); + WritePH(phdr[bss]) END; FOR i := 0 TO lenInterpreter - 1 DO - WR.WriteByte(File, ORD(Interpreter[i])) + WR.WriteByte(ORD(Interpreter[i])) END; - i := 0; IF amd64 THEN item := dynamic.first; WHILE item # NIL DO - WR.Write64LE(File, item(Elf32_Dyn).d_tag); - WR.Write64LE(File, item(Elf32_Dyn).d_val); + WR.Write64LE(item(Elf32_Dyn).d_tag); + WR.Write64LE(item(Elf32_Dyn).d_val); item := item.next END; item := symtab.first; WHILE item # NIL DO - WR.Write32LE(File, item(Elf32_Sym).name); - WR.WriteByte(File, ORD(item(Elf32_Sym).info)); - WR.WriteByte(File, ORD(item(Elf32_Sym).other)); - Write16(File, item(Elf32_Sym).shndx); - WR.Write64LE(File, item(Elf32_Sym).value); - WR.Write64LE(File, item(Elf32_Sym).size); + WR.Write32LE(item(Elf32_Sym).name); + WR.WriteByte(ORD(item(Elf32_Sym).info)); + WR.WriteByte(ORD(item(Elf32_Sym).other)); + Write16(item(Elf32_Sym).shndx); + WR.Write64LE(item(Elf32_Sym).value); + WR.Write64LE(item(Elf32_Sym).size); item := item.next END; - WR.Write64LE(File, phdr[dyn].p_filesz + Offset.dyn + BaseAdr - 16); - WR.Write32LE(File, 1); - WR.Write32LE(File, 1); - WR.Write64LE(File, 0); - WR.Write64LE(File, phdr[dyn].p_filesz + Offset.dyn + BaseAdr - 8); - WR.Write32LE(File, 1); - WR.Write32LE(File, 2); - WR.Write64LE(File, 0); - - WR.Write32LE(File, symCount); - WR.Write32LE(File, symCount); - - FOR i := 0 TO symCount - 1 DO - WR.Write32LE(File, CHL.GetInt(bucket, i)) - END; - - FOR i := 0 TO symCount - 1 DO - WR.Write32LE(File, CHL.GetInt(chain, i)) - END; - - CHL.WriteToFile(File, strtab); - WR.Write64LE(File, 0); - WR.Write64LE(File, 0) + WR.Write64LE(phdr[dyn].p_filesz + DynAdr - 16); + WR.Write32LE(1); + WR.Write32LE(1); + WR.Write64LE(0); + WR.Write64LE(phdr[dyn].p_filesz + DynAdr - 8); + WR.Write32LE(1); + WR.Write32LE(2); + WR.Write64LE(0) ELSE item := dynamic.first; WHILE item # NIL DO - WR.Write32LE(File, item(Elf32_Dyn).d_tag); - WR.Write32LE(File, item(Elf32_Dyn).d_val); + WR.Write32LE(item(Elf32_Dyn).d_tag); + WR.Write32LE(item(Elf32_Dyn).d_val); item := item.next END; item := symtab.first; WHILE item # NIL DO - WR.Write32LE(File, item(Elf32_Sym).name); - WR.Write32LE(File, item(Elf32_Sym).value); - WR.Write32LE(File, item(Elf32_Sym).size); - WR.WriteByte(File, ORD(item(Elf32_Sym).info)); - WR.WriteByte(File, ORD(item(Elf32_Sym).other)); - Write16(File, item(Elf32_Sym).shndx); + WR.Write32LE(item(Elf32_Sym).name); + WR.Write32LE(item(Elf32_Sym).value); + WR.Write32LE(item(Elf32_Sym).size); + WR.WriteByte(ORD(item(Elf32_Sym).info)); + WR.WriteByte(ORD(item(Elf32_Sym).other)); + Write16(item(Elf32_Sym).shndx); item := item.next END; - WR.Write32LE(File, phdr[dyn].p_filesz + Offset.dyn + BaseAdr - 8); - WR.Write32LE(File, 00000101H); - WR.Write32LE(File, phdr[dyn].p_filesz + Offset.dyn + BaseAdr - 4); - WR.Write32LE(File, 00000201H); - - WR.Write32LE(File, symCount); - WR.Write32LE(File, symCount); - - FOR i := 0 TO symCount - 1 DO - WR.Write32LE(File, CHL.GetInt(bucket, i)) - END; - - FOR i := 0 TO symCount - 1 DO - WR.Write32LE(File, CHL.GetInt(chain, i)) - END; - - CHL.WriteToFile(File, strtab); - WR.Write32LE(File, 0); - WR.Write32LE(File, 0) + WR.Write32LE(phdr[dyn].p_filesz + DynAdr - 8); + WR.Write32LE(00000101H); + WR.Write32LE(phdr[dyn].p_filesz + DynAdr - 4); + WR.Write32LE(00000201H) END; + + WR.Write32LE(symCount); + WR.Write32LE(symCount); - CHL.WriteToFile(File, program.code); + FOR i := 0 TO symCount - 1 DO + WR.Write32LE(CHL.GetInt(bucket, i)) + END; + + FOR i := 0 TO symCount - 1 DO + WR.Write32LE(CHL.GetInt(chain, i)) + END; + + CHL.WriteToFile(strtab); + + IF amd64 THEN + WR.Write64LE(0); + WR.Write64LE(0) + ELSE + WR.Write32LE(0); + WR.Write32LE(0) + END; + + CHL.WriteToFile(program.code); WHILE pad > 0 DO - WR.WriteByte(File, 0); + WR.WriteByte(0); DEC(pad) END; - CHL.WriteToFile(File, program.data); - WR.Close(File) + CHL.WriteToFile(program.data); + WR.Close; + UTILS.chmod(FileName) END write; diff --git a/programs/develop/oberon07/Source/ERRORS.ob07 b/programs/develop/oberon07/Source/ERRORS.ob07 index b925b6fe5..872b2ef29 100644 --- a/programs/develop/oberon07/Source/ERRORS.ob07 +++ b/programs/develop/oberon07/Source/ERRORS.ob07 @@ -144,7 +144,9 @@ BEGIN |114: str := "identifiers 'lib_init' and 'version' are reserved" |115: str := "recursive constant definition" |116: str := "procedure too deep nested" - + |117: str := "string expected" + |118: str := "'$END', '$ELSE' or '$ELSIF' without '$IF'" + |119: str := "'$IF', '$ELSIF', '$ELSE' or '$END' expected" |120: str := "too many formal parameters" |121: str := "multiply defined handler" |122: str := "bad divisor" @@ -210,6 +212,7 @@ BEGIN |205: Error1("not enough parameters") |206: Error1("bad parameter ") |207: Error3('inputfile name extension must be "', UTILS.FILE_EXT, '"') + |208: Error1("not enough RAM") END END Error; diff --git a/programs/develop/oberon07/Source/FILES.ob07 b/programs/develop/oberon07/Source/FILES.ob07 index 1ef926ca0..07c906bc0 100644 --- a/programs/develop/oberon07/Source/FILES.ob07 +++ b/programs/develop/oberon07/Source/FILES.ob07 @@ -17,9 +17,7 @@ TYPE ptr: INTEGER; buffer: ARRAY 64*1024 OF BYTE; - count: INTEGER; - - chksum*: INTEGER + count: INTEGER END; @@ -85,8 +83,7 @@ BEGIN IF ptr > 0 THEN file := NewFile(); file.ptr := ptr; - file.count := 0; - file.chksum := 0 + file.count := 0 ELSE file := NIL END diff --git a/programs/develop/oberon07/Source/HEX.ob07 b/programs/develop/oberon07/Source/HEX.ob07 index 2bfbdd80e..c1f35780f 100644 --- a/programs/develop/oberon07/Source/HEX.ob07 +++ b/programs/develop/oberon07/Source/HEX.ob07 @@ -7,120 +7,110 @@ MODULE HEX; -IMPORT FILES, WRITER, CHL := CHUNKLISTS; +IMPORT WRITER, CHL := CHUNKLISTS, UTILS; -PROCEDURE hexdgt (n: BYTE): BYTE; +VAR + + chksum: INTEGER; + + +PROCEDURE Byte (byte: BYTE); BEGIN - IF n < 10 THEN - n := n + ORD("0") - ELSE - n := n - 10 + ORD("A") - END - - RETURN n -END hexdgt; - - -PROCEDURE Byte (file: FILES.FILE; byte: BYTE); -BEGIN - WRITER.WriteByte(file, hexdgt(byte DIV 16)); - WRITER.WriteByte(file, hexdgt(byte MOD 16)); - INC(file.chksum, byte); + WRITER.WriteByte(UTILS.hexdgt(byte DIV 16)); + WRITER.WriteByte(UTILS.hexdgt(byte MOD 16)); + INC(chksum, byte) END Byte; -PROCEDURE NewLine (file: FILES.FILE); +PROCEDURE Byte4 (a, b, c, d: BYTE); BEGIN - Byte(file, (-file.chksum) MOD 256); - file.chksum := 0; - WRITER.WriteByte(file, 0DH); - WRITER.WriteByte(file, 0AH) + Byte(a); + Byte(b); + Byte(c); + Byte(d) +END Byte4; + + +PROCEDURE NewLine; +BEGIN + Byte((-chksum) MOD 256); + chksum := 0; + WRITER.WriteByte(0DH); + WRITER.WriteByte(0AH) END NewLine; -PROCEDURE StartCode (file: FILES.FILE); +PROCEDURE StartCode; BEGIN - WRITER.WriteByte(file, ORD(":")); - file.chksum := 0 + WRITER.WriteByte(ORD(":")); + chksum := 0 END StartCode; -PROCEDURE Data* (file: FILES.FILE; mem: ARRAY OF BYTE; idx, cnt: INTEGER); +PROCEDURE Data* (mem: ARRAY OF BYTE; idx, cnt: INTEGER); VAR i, len: INTEGER; BEGIN WHILE cnt > 0 DO len := MIN(cnt, 16); - StartCode(file); - Byte(file, len); - Byte(file, idx DIV 256); - Byte(file, idx MOD 256); - Byte(file, 0); + StartCode; + Byte4(len, idx DIV 256, idx MOD 256, 0); FOR i := 1 TO len DO - Byte(file, mem[idx]); + Byte(mem[idx]); INC(idx) END; DEC(cnt, len); - NewLine(file) + NewLine END END Data; -PROCEDURE ExtLA* (file: FILES.FILE; LA: INTEGER); +PROCEDURE ExtLA* (LA: INTEGER); BEGIN ASSERT((0 <= LA) & (LA <= 0FFFFH)); - StartCode(file); - Byte(file, 2); - Byte(file, 0); - Byte(file, 0); - Byte(file, 4); - Byte(file, LA DIV 256); - Byte(file, LA MOD 256); - NewLine(file) + StartCode; + Byte4(2, 0, 0, 4); + Byte(LA DIV 256); + Byte(LA MOD 256); + NewLine END ExtLA; -PROCEDURE Data2* (file: FILES.FILE; mem: CHL.BYTELIST; idx, cnt, LA: INTEGER); +PROCEDURE Data2* (mem: CHL.BYTELIST; idx, cnt, LA: INTEGER); VAR i, len, offset: INTEGER; BEGIN - ExtLA(file, LA); + ExtLA(LA); offset := 0; WHILE cnt > 0 DO ASSERT(offset <= 65536); IF offset = 65536 THEN INC(LA); - ExtLA(file, LA); + ExtLA(LA); offset := 0 END; len := MIN(cnt, 16); - StartCode(file); - Byte(file, len); - Byte(file, offset DIV 256); - Byte(file, offset MOD 256); - Byte(file, 0); + StartCode; + Byte4(len, offset DIV 256, offset MOD 256, 0); FOR i := 1 TO len DO - Byte(file, CHL.GetByte(mem, idx)); + Byte(CHL.GetByte(mem, idx)); INC(idx); INC(offset) END; DEC(cnt, len); - NewLine(file) + NewLine END END Data2; -PROCEDURE End* (file: FILES.FILE); +PROCEDURE End*; BEGIN - StartCode(file); - Byte(file, 0); - Byte(file, 0); - Byte(file, 0); - Byte(file, 1); - NewLine(file) + StartCode; + Byte4(0, 0, 0, 1); + NewLine END End; diff --git a/programs/develop/oberon07/Source/IL.ob07 b/programs/develop/oberon07/Source/IL.ob07 index 48e7d7eda..cd1cd43bf 100644 --- a/programs/develop/oberon07/Source/IL.ob07 +++ b/programs/develop/oberon07/Source/IL.ob07 @@ -7,14 +7,11 @@ MODULE IL; -IMPORT LISTS, SCAN, STRINGS, CHL := CHUNKLISTS, C := COLLECTIONS, TARGETS; +IMPORT LISTS, SCAN, STRINGS, CHL := CHUNKLISTS, C := COLLECTIONS, TARGETS, PATHS; CONST - little_endian* = 0; - big_endian* = 1; - call_stack* = 0; call_win64* = 1; call_sysv* = 2; @@ -22,7 +19,7 @@ CONST opJMP* = 0; opLABEL* = 1; opCOPYS* = 2; opGADR* = 3; opCONST* = 4; opLLOAD32* = 5; opCOPYA* = 6; opCASET* = 7; opMULC* = 8; opMUL* = 9; opDIV* = 10; opMOD* = 11; opDIVL* = 12; opMODL* = 13; opDIVR* = 14; opMODR* = 15; opUMINUS* = 16; - opADD* = 17; opSUB* = 18; opADDL* = 19; opSUBL* = 20; opADDR* = 21; opSUBR* = 22; + opADD* = 17; opSUB* = 18; opONERR* = 19; opSUBL* = 20; opADDC* = 21; opSUBR* = 22; opSAVE* = 23; opSAVEC* = 24; opSAVE8* = 25; opSAVE8C* = 26; opCHKBYTE* = 27; opDROP* = 28; opNOT* = 29; @@ -34,14 +31,14 @@ CONST opVLOAD32* = 60; opGLOAD32* = 61; - opJNE* = 62; opJE* = 63; + opJZ* = 62; opJNZ* = 63; opSAVE32* = 64; opLLOAD8* = 65; opCONSTF* = 66; opLOADF* = 67; opSAVEF* = 68; opMULF* = 69; opDIVF* = 70; opDIVFI* = 71; - opUMINF* = 72; opADDFI* = 73; opSUBFI* = 74; opADDF* = 75; opSUBF* = 76; + opUMINF* = 72; opSAVEFI* = 73; opSUBFI* = 74; opADDF* = 75; opSUBF* = 76; - opACC* = 77; opJG* = 78; + opJNZ1* = 77; opJG* = 78; opINCCB* = 79; opDECCB* = 80; opINCB* = 81; opDECB* = 82; opCASEL* = 83; opCASER* = 84; opCASELR* = 85; @@ -55,7 +52,7 @@ CONST opSBOOL* = 100; opSBOOLC* = 101; opNOP* = 102; opMULS* = 103; opMULSC* = 104; opDIVS* = 105; opDIVSC* = 106; - opADDS* = 107; opSUBS* = 108; opADDSL* = 109; opSUBSL* = 110; opADDSR* = 111; opSUBSR* = 112; + opADDS* = 107; opSUBS* = 108; opERR* = 109; opSUBSL* = 110; opADDSC* = 111; opSUBSR* = 112; opUMINS* = 113; opIN* = 114; opINL* = 115; opINR* = 116; opRSET* = 117; opRSETL* = 118; opRSETR* = 119; opRSET1* = 120; opLENGTH* = 121; @@ -65,25 +62,24 @@ CONST opPACK* = 134; opPACKC* = 135; opUNPK* = 136; opCOPY* = 137; opENTER* = 138; opLEAVE* = 139; opCALL* = 140; opSAVEP* = 141; opCALLP* = 142; opEQP* = 143; opNEP* = 144; opLEAVER* = 145; opGET* = 146; opSAVE16* = 147; opABS* = 148; opFABS* = 149; opFLOOR* = 150; opFLT* = 151; - opORD* = 153; opASR* = 154; opLSL* = 155; opROR* = 156; + opGETC* = 152; opORD* = 153; opASR* = 154; opLSL* = 155; opROR* = 156; opASR1* = 157; opLSL1* = 158; opROR1* = 159; opASR2* = 160; opLSL2* = 161; opROR2* = 162; opPUSHP* = 163; opLADR* = 164; opTYPEGP* = 165; opIS* = 166; opPUSHF* = 167; opVADR* = 168; opPUSHT* = 169; opTYPEGR* = 170; opISREC* = 171; opCHKIDX* = 172; opPARAM* = 173; - opCHKIDX2* = 174; opLEN* = 175; opROT* = 176; opSAVES* = 177; opSADR* = 178; opERR* = 179; + opCHKIDX2* = 174; opLEN* = 175; opROT* = 176; opSAVES* = 177; opSADR* = 178; opLENGTHW* = 179; opCHR* = 180; opENDSW* = 181; opLEAVEF* = 182; opCLEANUP* = 183; opMOVE* = 184; opLSR* = 185; opLSR1* = 186; opLSR2* = 187; - opMIN* = 188; opMINC* = 189; opMAX* = 190; opMAXC* = 191; opJNZ* = 192; - opEQB* = 193; opNEB* = 194; opINF* = 195; opJZ* = 196; opVLOAD8* = 197; opGLOAD8* = 198; + opMIN* = 188; opMINC* = 189; opMAX* = 190; opMAXC* = 191; opSYSVALIGN16* = 192; + opEQB* = 193; opNEB* = 194; opINF* = 195; opWIN64ALIGN16* = 196; opVLOAD8* = 197; opGLOAD8* = 198; opLLOAD16* = 199; opVLOAD16* = 200; opGLOAD16* = 201; opLOAD64* = 202; opLLOAD64* = 203; opVLOAD64* = 204; opGLOAD64* = 205; opSAVE64* = 206; opTYPEGD* = 207; opCALLI* = 208; opPUSHIP* = 209; opSAVEIP* = 210; opEQIP* = 211; opNEIP* = 212; - opSAVE16C* = 213; opWCHR* = 214; opGETC* = 215; opLENGTHW* = 216; + opSAVE16C* = 213; opWCHR* = 214; opHANDLER* = 215; - opSYSVCALL* = 217; opSYSVCALLI* = 218; opSYSVCALLP* = 219; opSYSVALIGN16* = 220; opWIN64ALIGN16* = 221; - - opONERR* = 222; opSAVEFI* = 223; opHANDLER* = 224; + opSYSVCALL* = 216; opSYSVCALLI* = 217; opSYSVCALLP* = 218; opFNAME* = 219; + opAND* = 220; opOR* = 221; opSADR_PARAM* = -1; opLOAD64_PARAM* = -2; opLLOAD64_PARAM* = -3; opGLOAD64_PARAM* = -4; @@ -154,6 +150,12 @@ TYPE END; + FNAMECMD* = POINTER TO RECORD (COMMAND) + + fname*: PATHS.PATH + + END; + CMDSTACK = POINTER TO RECORD data: ARRAY 1000 OF COMMAND; @@ -192,7 +194,7 @@ TYPE endcall: CMDSTACK; commands*: LISTS.LIST; export*: LISTS.LIST; - import*: LISTS.LIST; + _import*: LISTS.LIST; types*: CHL.INTLIST; data*: CHL.BYTELIST; dmin*: INTEGER; @@ -204,7 +206,6 @@ TYPE charoffs: ARRAY 256 OF INTEGER; wcharoffs: ARRAY 65536 OF INTEGER; - fregs: INTEGER; wstr: ARRAY 4*1024 OF WCHAR END; @@ -212,7 +213,7 @@ TYPE VAR codes*: CODES; - endianness, numRegsFloat, CPU: INTEGER; + CPU: INTEGER; commands, variables: C.COLLECTION; @@ -343,10 +344,10 @@ BEGIN i := 0; WHILE i < n DO - IF endianness = little_endian THEN + IF TARGETS.LittleEndian THEN PutByte(ORD(codes.wstr[i]) MOD 256); PutByte(ORD(codes.wstr[i]) DIV 256) - ELSIF endianness = big_endian THEN + ELSE PutByte(ORD(codes.wstr[i]) DIV 256); PutByte(ORD(codes.wstr[i]) MOD 256) END; @@ -373,10 +374,10 @@ BEGIN INC(res) END; - IF endianness = little_endian THEN + IF TARGETS.LittleEndian THEN PutByte(c MOD 256); PutByte(c DIV 256) - ELSIF endianness = big_endian THEN + ELSE PutByte(c DIV 256); PutByte(c MOD 256) END; @@ -410,19 +411,19 @@ BEGIN END pop; -PROCEDURE pushBegEnd* (VAR beg, end: COMMAND); +PROCEDURE pushBegEnd* (VAR beg, _end: COMMAND); BEGIN push(codes.begcall, beg); - push(codes.endcall, end); + push(codes.endcall, _end); beg := codes.last; - end := beg.next(COMMAND) + _end := beg.next(COMMAND) END pushBegEnd; -PROCEDURE popBegEnd* (VAR beg, end: COMMAND); +PROCEDURE popBegEnd* (VAR beg, _end: COMMAND); BEGIN beg := pop(codes.begcall); - end := pop(codes.endcall) + _end := pop(codes.endcall) END popBegEnd; @@ -494,6 +495,9 @@ BEGIN ELSIF (nov.opcode = opMULC) & (old_opcode = opMULC) THEN cur.param2 := param2 * cur.param2 + ELSIF (nov.opcode = opADDC) & (old_opcode = opADDC) THEN + cur.param2 := param2 + cur.param2 + ELSE old_opcode := -1 END @@ -631,10 +635,10 @@ BEGIN prev := codes.last; not := prev.opcode = opNOT; IF not THEN - IF opcode = opJE THEN - opcode := opJNE - ELSIF opcode = opJNE THEN - opcode := opJE + IF opcode = opJNZ THEN + opcode := opJZ + ELSIF opcode = opJZ THEN + opcode := opJNZ ELSE not := FALSE END @@ -645,10 +649,79 @@ BEGIN IF not THEN delete(prev) END - END AddJmpCmd; +PROCEDURE AndOrOpt* (VAR label: INTEGER); +VAR + cur, prev: COMMAND; + i, op, l: INTEGER; + jz, not: BOOLEAN; + +BEGIN + cur := codes.last; + not := cur.opcode = opNOT; + IF not THEN + cur := cur.prev(COMMAND) + END; + + IF cur.opcode = opAND THEN + op := opAND + ELSIF cur.opcode = opOR THEN + op := opOR + ELSE + op := -1 + END; + + cur := codes.last; + + IF op # -1 THEN + IF not THEN + IF op = opAND THEN + op := opOR + ELSE (* op = opOR *) + op := opAND + END; + prev := cur.prev(COMMAND); + delete(cur); + cur := prev + END; + + FOR i := 1 TO 9 DO + IF i = 8 THEN + l := cur.param1 + ELSIF i = 9 THEN + jz := cur.opcode = opJZ + END; + prev := cur.prev(COMMAND); + delete(cur); + cur := prev + END; + + setlast(cur); + + IF op = opAND THEN + label := l; + jz := ~jz + END; + + IF jz THEN + AddJmpCmd(opJZ, label) + ELSE + AddJmpCmd(opJNZ, label) + END; + + IF op = opOR THEN + SetLabel(l) + END + ELSE + AddJmpCmd(opJZ, label) + END; + + setlast(codes.last) +END AndOrOpt; + + PROCEDURE OnError* (line, error: INTEGER); BEGIN AddCmd2(opONERR, codes.errlabels[error], line) @@ -661,7 +734,7 @@ VAR BEGIN AddCmd(op, t); label := NewLabel(); - AddJmpCmd(opJE, label); + AddJmpCmd(opJNZ, label); OnError(line, error); SetLabel(label) END TypeGuard; @@ -685,14 +758,6 @@ BEGIN END New; -PROCEDURE fcmp* (opcode: INTEGER); -BEGIN - AddCmd(opcode, 0); - DEC(codes.fregs, 2); - ASSERT(codes.fregs >= 0) -END fcmp; - - PROCEDURE not*; VAR prev: COMMAND; @@ -707,6 +772,14 @@ BEGIN END not; +PROCEDURE _ord*; +BEGIN + IF (codes.last.opcode # opAND) & (codes.last.opcode # opOR) THEN + AddCmd0(opORD) + END +END _ord; + + PROCEDURE Enter* (label, params: INTEGER): COMMAND; VAR cmd: COMMAND; @@ -900,44 +973,10 @@ BEGIN AddCmd0(opSAVEFI) ELSE AddCmd0(opSAVEF) - END; - DEC(codes.fregs); - ASSERT(codes.fregs >= 0) + END END savef; -PROCEDURE pushf*; -BEGIN - AddCmd0(opPUSHF); - DEC(codes.fregs); - ASSERT(codes.fregs >= 0) -END pushf; - - -PROCEDURE loadf* (): BOOLEAN; -BEGIN - AddCmd0(opLOADF); - INC(codes.fregs) - RETURN codes.fregs < numRegsFloat -END loadf; - - -PROCEDURE inf* (): BOOLEAN; -BEGIN - AddCmd0(opINF); - INC(codes.fregs) - RETURN codes.fregs < numRegsFloat -END inf; - - -PROCEDURE fbinop* (opcode: INTEGER); -BEGIN - AddCmd0(opcode); - DEC(codes.fregs); - ASSERT(codes.fregs > 0) -END fbinop; - - PROCEDURE saves* (offset, length: INTEGER); BEGIN AddCmd2(opSAVES, length, offset) @@ -954,22 +993,6 @@ BEGIN END abs; -PROCEDURE floor*; -BEGIN - AddCmd0(opFLOOR); - DEC(codes.fregs); - ASSERT(codes.fregs >= 0) -END floor; - - -PROCEDURE flt* (): BOOLEAN; -BEGIN - AddCmd0(opFLT); - INC(codes.fregs) - RETURN codes.fregs < numRegsFloat -END flt; - - PROCEDURE shift_minmax* (op: CHAR); BEGIN CASE op OF @@ -1015,7 +1038,7 @@ BEGIN END len; -PROCEDURE Float* (r: REAL); +PROCEDURE Float* (r: REAL; line, col: INTEGER); VAR cmd: COMMAND; @@ -1023,52 +1046,19 @@ BEGIN cmd := NewCmd(); cmd.opcode := opCONSTF; cmd.float := r; - insert(codes.last, cmd); - INC(codes.fregs); - ASSERT(codes.fregs <= numRegsFloat) + cmd.param1 := line; + cmd.param2 := col; + insert(codes.last, cmd) END Float; -PROCEDURE precall* (flt: BOOLEAN): INTEGER; -VAR - res: INTEGER; -BEGIN - res := codes.fregs; - AddCmd2(opPRECALL, ORD(flt), res); - codes.fregs := 0 - RETURN res -END precall; - - -PROCEDURE resf* (fregs: INTEGER): BOOLEAN; -BEGIN - AddCmd(opRESF, fregs); - codes.fregs := fregs + 1 - RETURN codes.fregs < numRegsFloat -END resf; - - -PROCEDURE res* (fregs: INTEGER); -BEGIN - AddCmd(opRES, fregs); - codes.fregs := fregs -END res; - - -PROCEDURE retf*; -BEGIN - DEC(codes.fregs); - ASSERT(codes.fregs = 0) -END retf; - - PROCEDURE drop*; BEGIN AddCmd0(opDROP) END drop; -PROCEDURE case* (a, b, L, R: INTEGER); +PROCEDURE _case* (a, b, L, R: INTEGER); VAR cmd: COMMAND; @@ -1084,13 +1074,19 @@ BEGIN AddCmd2(opCASEL, a, L); AddCmd2(opCASER, b, R) END -END case; +END _case; -PROCEDURE caset* (a, label: INTEGER); +PROCEDURE fname* (name: PATHS.PATH); +VAR + cmd: FNAMECMD; + BEGIN - AddCmd2(opCASET, label, a) -END caset; + NEW(cmd); + cmd.opcode := opFNAME; + cmd.fname := name; + insert(codes.last, cmd) +END fname; PROCEDURE AddExp* (label: INTEGER; name: SCAN.LEXSTR); @@ -1111,7 +1107,7 @@ VAR p: IMPORT_PROC; BEGIN - lib := codes.import.first(IMPORT_LIB); + lib := codes._import.first(IMPORT_LIB); WHILE (lib # NIL) & (lib.name # dll) DO lib := lib.next(IMPORT_LIB) END; @@ -1120,7 +1116,7 @@ BEGIN NEW(lib); lib.name := dll; lib.procs := LISTS.create(NIL); - LISTS.push(codes.import, lib) + LISTS.push(codes._import, lib) END; p := lib.procs.first(IMPORT_PROC); @@ -1153,7 +1149,7 @@ BEGIN lib := imp(IMPORT_PROC).lib; LISTS.delete(lib.procs, imp); IF lib.procs.first = NIL THEN - LISTS.delete(codes.import, lib) + LISTS.delete(codes._import, lib) END END END DelImport; @@ -1161,21 +1157,14 @@ END DelImport; PROCEDURE init* (pCPU: INTEGER); VAR - cmd: COMMAND; - i: INTEGER; + cmd: COMMAND; + i: INTEGER; BEGIN commands := C.create(); variables := C.create(); CPU := pCPU; - endianness := little_endian; - CASE CPU OF - |TARGETS.cpuAMD64: numRegsFloat := 6 - |TARGETS.cpuX86: numRegsFloat := 8 - |TARGETS.cpuMSP430: numRegsFloat := 0 - |TARGETS.cpuTHUMB: numRegsFloat := 256 - END; NEW(codes.begcall); codes.begcall.top := -1; @@ -1183,7 +1172,7 @@ BEGIN codes.endcall.top := -1; codes.commands := LISTS.create(NIL); codes.export := LISTS.create(NIL); - codes.import := LISTS.create(NIL); + codes._import := LISTS.create(NIL); codes.types := CHL.CreateIntList(); codes.data := CHL.CreateByteList(); @@ -1195,8 +1184,6 @@ BEGIN codes.lcount := 0; - codes.fregs := 0; - FOR i := 0 TO LEN(codes.charoffs) - 1 DO codes.charoffs[i] := -1 END; diff --git a/programs/develop/oberon07/Source/KOS.ob07 b/programs/develop/oberon07/Source/KOS.ob07 index 7f6b0aed7..979a8cfeb 100644 --- a/programs/develop/oberon07/Source/KOS.ob07 +++ b/programs/develop/oberon07/Source/KOS.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018-2019, Anton Krotov + Copyright (c) 2018-2020, Anton Krotov All rights reserved. *) @@ -19,8 +19,6 @@ CONST TYPE - FILE = WR.FILE; - HEADER = RECORD menuet01: ARRAY 9 OF CHAR; @@ -29,29 +27,19 @@ TYPE END; -PROCEDURE align (n, _align: INTEGER): INTEGER; -BEGIN - IF n MOD _align # 0 THEN - n := n + _align - (n MOD _align) - END - - RETURN n -END align; - - PROCEDURE Import* (program: BIN.PROGRAM; idata: INTEGER; VAR ImportTable: CHL.INTLIST; VAR len, libcount, size: INTEGER); VAR - i: INTEGER; - import: BIN.IMPRT; + i: INTEGER; + imp: BIN.IMPRT; BEGIN libcount := 0; - import := program.imp_list.first(BIN.IMPRT); - WHILE import # NIL DO - IF import.label = 0 THEN + imp := program.imp_list.first(BIN.IMPRT); + WHILE imp # NIL DO + IF imp.label = 0 THEN INC(libcount) END; - import := import.next(BIN.IMPRT) + imp := imp.next(BIN.IMPRT) END; len := libcount * 2 + 2; @@ -63,29 +51,29 @@ BEGIN END; i := 0; - import := program.imp_list.first(BIN.IMPRT); - WHILE import # NIL DO + imp := program.imp_list.first(BIN.IMPRT); + WHILE imp # NIL DO - IF import.label = 0 THEN + IF imp.label = 0 THEN CHL.SetInt(ImportTable, len, 0); INC(len); CHL.SetInt(ImportTable, i, idata + len * SIZE_OF_DWORD); INC(i); - CHL.SetInt(ImportTable, i, import.nameoffs + size + idata); + CHL.SetInt(ImportTable, i, imp.nameoffs + size + idata); INC(i) ELSE - CHL.SetInt(ImportTable, len, import.nameoffs + size + idata); - import.label := len * SIZE_OF_DWORD; + CHL.SetInt(ImportTable, len, imp.nameoffs + size + idata); + imp.label := len * SIZE_OF_DWORD; INC(len) END; - import := import.next(BIN.IMPRT) + imp := imp.next(BIN.IMPRT) END; CHL.SetInt(ImportTable, len, 0); CHL.SetInt(ImportTable, i, 0); CHL.SetInt(ImportTable, i + 1, 0); INC(len); - size := size + CHL.Length(program.import) + INC(size, CHL.Length(program._import)) END Import; @@ -100,7 +88,7 @@ CONST VAR header: HEADER; - base, text, data, idata, bss: INTEGER; + base, text, data, idata, bss, offset: INTEGER; reloc: BIN.RELOC; iproc: BIN.IMPRT; @@ -109,8 +97,6 @@ VAR i: INTEGER; - File: FILE; - ImportTable: CHL.INTLIST; ILen, libcount, isize: INTEGER; @@ -121,23 +107,23 @@ VAR BEGIN base := 0; - icount := CHL.Length(program.import); + icount := CHL.Length(program._import); dcount := CHL.Length(program.data); ccount := CHL.Length(program.code); text := base + HEADER_SIZE; - data := align(text + ccount, FileAlignment); - idata := align(data + dcount, FileAlignment); + data := WR.align(text + ccount, FileAlignment); + idata := WR.align(data + dcount, FileAlignment); Import(program, idata, ImportTable, ILen, libcount, isize); - bss := align(idata + isize, FileAlignment); + bss := WR.align(idata + isize, FileAlignment); header.menuet01 := "MENUET01"; header.ver := 1; header.start := text; header.size := idata + isize - base; - header.mem := align(header.size + program.stack + program.bss + PARAM_SIZE * 2 + 4096, FileAlignment); + header.mem := WR.align(header.size + program.stack + program.bss + PARAM_SIZE * 2 + 4096, FileAlignment); header.sp := base + header.mem - PARAM_SIZE * 2; header.param := header.sp; header.path := header.param + PARAM_SIZE; @@ -146,73 +132,74 @@ BEGIN reloc := program.rel_list.first(BIN.RELOC); WHILE reloc # NIL DO - L := BIN.get32le(code, reloc.offset); - delta := 3 - reloc.offset - text; + offset := reloc.offset; + L := BIN.get32le(code, offset); + delta := 3 - offset - text; CASE reloc.opcode OF |BIN.RIMP: iproc := BIN.GetIProc(program, L); - BIN.put32le(code, reloc.offset, idata + iproc.label) + delta := idata + iproc.label |BIN.RBSS: - BIN.put32le(code, reloc.offset, L + bss) + delta := L + bss |BIN.RDATA: - BIN.put32le(code, reloc.offset, L + data) + delta := L + data |BIN.RCODE: - BIN.put32le(code, reloc.offset, BIN.GetLabel(program, L) + text) + delta := BIN.GetLabel(program, L) + text |BIN.PICDATA: - BIN.put32le(code, reloc.offset, L + data + delta) + INC(delta, L + data) |BIN.PICCODE: - BIN.put32le(code, reloc.offset, BIN.GetLabel(program, L) + text + delta) + INC(delta, BIN.GetLabel(program, L) + text) |BIN.PICBSS: - BIN.put32le(code, reloc.offset, L + bss + delta) + INC(delta, L + bss) |BIN.PICIMP: iproc := BIN.GetIProc(program, L); - BIN.put32le(code, reloc.offset, idata + iproc.label + delta) + INC(delta, idata + iproc.label) |BIN.IMPTAB: - BIN.put32le(code, reloc.offset, idata + delta) + INC(delta, idata) END; + BIN.put32le(code, offset, delta); reloc := reloc.next(BIN.RELOC) END; - File := WR.Create(FileName); + WR.Create(FileName); FOR i := 0 TO 7 DO - WR.WriteByte(File, ORD(header.menuet01[i])) + WR.WriteByte(ORD(header.menuet01[i])) END; - WR.Write32LE(File, header.ver); - WR.Write32LE(File, header.start); - WR.Write32LE(File, header.size); - WR.Write32LE(File, header.mem); - WR.Write32LE(File, header.sp); - WR.Write32LE(File, header.param); - WR.Write32LE(File, header.path); + WR.Write32LE(header.ver); + WR.Write32LE(header.start); + WR.Write32LE(header.size); + WR.Write32LE(header.mem); + WR.Write32LE(header.sp); + WR.Write32LE(header.param); + WR.Write32LE(header.path); - CHL.WriteToFile(File, code); - WR.Padding(File, FileAlignment); + CHL.WriteToFile(code); + WR.Padding(FileAlignment); - CHL.WriteToFile(File, program.data); - WR.Padding(File, FileAlignment); + CHL.WriteToFile(program.data); + WR.Padding(FileAlignment); FOR i := 0 TO ILen - 1 DO - WR.Write32LE(File, CHL.GetInt(ImportTable, i)) + WR.Write32LE(CHL.GetInt(ImportTable, i)) END; - CHL.WriteToFile(File, program.import); - - WR.Close(File) + CHL.WriteToFile(program._import); + WR.Close END write; diff --git a/programs/develop/oberon07/Source/LISTS.ob07 b/programs/develop/oberon07/Source/LISTS.ob07 index d9a8bcc2a..4cb60d21e 100644 --- a/programs/develop/oberon07/Source/LISTS.ob07 +++ b/programs/develop/oberon07/Source/LISTS.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018-2019, Anton Krotov + Copyright (c) 2018-2020, Anton Krotov All rights reserved. *) @@ -32,17 +32,14 @@ BEGIN IF list.first = NIL THEN list.first := item; - list.last := item; - item.prev := NIL; - item.next := NIL + item.prev := NIL ELSE ASSERT(list.last # NIL); - item.prev := list.last; - list.last.next := item; - item.next := NIL; - list.last := item - END + list.last.next := item + END; + list.last := item; + item.next := NIL END push; @@ -108,16 +105,13 @@ BEGIN IF prev # NIL THEN prev.next := nov; - nov.prev := prev; - cur.prev := nov; - nov.next := cur + nov.prev := prev ELSE nov.prev := NIL; - cur.prev := nov; - nov.next := cur; list.first := nov - END - + END; + cur.prev := nov; + nov.next := cur END insertL; diff --git a/programs/develop/oberon07/Source/MSCOFF.ob07 b/programs/develop/oberon07/Source/MSCOFF.ob07 index cc37bea1e..d6b878b39 100644 --- a/programs/develop/oberon07/Source/MSCOFF.ob07 +++ b/programs/develop/oberon07/Source/MSCOFF.ob07 @@ -28,28 +28,30 @@ TYPE SH = PE32.IMAGE_SECTION_HEADER; -PROCEDURE WriteReloc (File: WR.FILE; VirtualAddress, SymbolTableIndex, Type: INTEGER); +PROCEDURE WriteReloc (VirtualAddress, SymbolTableIndex, Type: INTEGER); BEGIN - WR.Write32LE(File, VirtualAddress); - WR.Write32LE(File, SymbolTableIndex); - WR.Write16LE(File, Type) + WR.Write32LE(VirtualAddress); + WR.Write32LE(SymbolTableIndex); + WR.Write16LE(Type) END WriteReloc; -PROCEDURE Reloc (program: BIN.PROGRAM; File: WR.FILE); +PROCEDURE Reloc (program: BIN.PROGRAM); VAR - reloc: BIN.RELOC; + reloc: BIN.RELOC; + offset: INTEGER; BEGIN reloc := program.rel_list.first(BIN.RELOC); WHILE reloc # NIL DO + offset := reloc.offset; CASE reloc.opcode OF |BIN.RIMP, - BIN.IMPTAB: WriteReloc(File, reloc.offset, 4, 6) - |BIN.RBSS: WriteReloc(File, reloc.offset, 5, 6) - |BIN.RDATA: WriteReloc(File, reloc.offset, 2, 6) - |BIN.RCODE: WriteReloc(File, reloc.offset, 1, 6) + BIN.IMPTAB: WriteReloc(offset, 4, 6) + |BIN.RBSS: WriteReloc(offset, 5, 6) + |BIN.RDATA: WriteReloc(offset, 2, 6) + |BIN.RCODE: WriteReloc(offset, 1, 6) END; reloc := reloc.next(BIN.RELOC) @@ -62,6 +64,7 @@ VAR reloc: BIN.RELOC; iproc: BIN.IMPRT; res, L: INTEGER; + offset: INTEGER; code: CHL.BYTELIST; BEGIN @@ -71,16 +74,17 @@ BEGIN WHILE reloc # NIL DO INC(res); + offset := reloc.offset; IF reloc.opcode = BIN.RIMP THEN - L := BIN.get32le(code, reloc.offset); + L := BIN.get32le(code, offset); iproc := BIN.GetIProc(program, L); - BIN.put32le(code, reloc.offset, iproc.label) + BIN.put32le(code, offset, iproc.label) END; IF reloc.opcode = BIN.RCODE THEN - L := BIN.get32le(code, reloc.offset); - BIN.put32le(code, reloc.offset, BIN.GetLabel(program, L)) + L := BIN.get32le(code, offset); + BIN.put32le(code, offset, BIN.GetLabel(program, L)) END; reloc := reloc.next(BIN.RELOC) @@ -92,7 +96,6 @@ END RelocCount; PROCEDURE write* (program: BIN.PROGRAM; FileName: ARRAY OF CHAR; ver: INTEGER); VAR - File: WR.FILE; exp: BIN.EXPRT; n, i: INTEGER; @@ -145,7 +148,7 @@ BEGIN KOS.Import(program, 0, ImportTable, ILen, LibCount, isize); ExpCount := LISTS.count(program.exp_list); - icount := CHL.Length(program.import); + icount := CHL.Length(program._import); dcount := CHL.Length(program.data); ccount := CHL.Length(program.code); ecount := CHL.Length(program.export); @@ -219,91 +222,87 @@ BEGIN FileHeader.PointerToSymbolTable := idata.PointerToRelocations + ORD(idata.NumberOfRelocations) * 10; - File := WR.Create(FileName); + WR.Create(FileName); - PE32.WriteFileHeader(File, FileHeader); + PE32.WriteFileHeader(FileHeader); - PE32.WriteSectionHeader(File, flat); - PE32.WriteSectionHeader(File, data); - PE32.WriteSectionHeader(File, edata); - PE32.WriteSectionHeader(File, idata); - PE32.WriteSectionHeader(File, bss); + PE32.WriteSectionHeader(flat); + PE32.WriteSectionHeader(data); + PE32.WriteSectionHeader(edata); + PE32.WriteSectionHeader(idata); + PE32.WriteSectionHeader(bss); - CHL.WriteToFile(File, program.code); - CHL.WriteToFile(File, program.data); + CHL.WriteToFile(program.code); + CHL.WriteToFile(program.data); exp := program.exp_list.first(BIN.EXPRT); WHILE exp # NIL DO - WR.Write32LE(File, exp.nameoffs + edata.SizeOfRawData - ecount); - WR.Write32LE(File, exp.label); + WR.Write32LE(exp.nameoffs + edata.SizeOfRawData - ecount); + WR.Write32LE(exp.label); exp := exp.next(BIN.EXPRT) END; - WR.Write32LE(File, ((ExpCount + 1) * 2 + 1) * SIZE_OF_DWORD); - WR.Write32LE(File, ver); + WR.Write32LE(((ExpCount + 1) * 2 + 1) * SIZE_OF_DWORD); + WR.Write32LE(ver); - WR.Write32LE(File, 0); + WR.Write32LE(0); - PE32.WriteName(File, szversion); - CHL.WriteToFile(File, program.export); + PE32.WriteName(szversion); + CHL.WriteToFile(program.export); FOR i := 0 TO ILen - 1 DO - WR.Write32LE(File, CHL.GetInt(ImportTable, i)) + WR.Write32LE(CHL.GetInt(ImportTable, i)) END; - CHL.WriteToFile(File, program.import); + CHL.WriteToFile(program._import); - Reloc(program, File); + Reloc(program); n := 0; exp := program.exp_list.first(BIN.EXPRT); WHILE exp # NIL DO - WriteReloc(File, n, 3, 6); + WriteReloc(n, 3, 6); INC(n, 4); - WriteReloc(File, n, 1, 6); + WriteReloc(n, 1, 6); INC(n, 4); exp := exp.next(BIN.EXPRT) END; - WriteReloc(File, n, 3, 6); + WriteReloc(n, 3, 6); - i := 0; - WHILE i < LibCount * 2 DO - WriteReloc(File, i * SIZE_OF_DWORD, 4, 6); - INC(i); - WriteReloc(File, i * SIZE_OF_DWORD, 4, 6); - INC(i) + FOR i := 0 TO LibCount * 2 - 1 DO + WriteReloc(i * SIZE_OF_DWORD, 4, 6) END; FOR i := LibCount * 2 TO ILen - 1 DO IF CHL.GetInt(ImportTable, i) # 0 THEN - WriteReloc(File, i * SIZE_OF_DWORD, 4, 6) + WriteReloc(i * SIZE_OF_DWORD, 4, 6) END END; - PE32.WriteName(File, "EXPORTS"); - WriteReloc(File, 0, 3, 2); + PE32.WriteName("EXPORTS"); + WriteReloc(0, 3, 2); - PE32.WriteName(File, ".flat"); - WriteReloc(File, 0, 1, 3); + PE32.WriteName(".flat"); + WriteReloc(0, 1, 3); - PE32.WriteName(File, ".data"); - WriteReloc(File, 0, 2, 3); + PE32.WriteName(".data"); + WriteReloc(0, 2, 3); - PE32.WriteName(File, ".edata"); - WriteReloc(File, 0, 3, 3); + PE32.WriteName(".edata"); + WriteReloc(0, 3, 3); - PE32.WriteName(File, ".idata"); - WriteReloc(File, 0, 4, 3); + PE32.WriteName(".idata"); + WriteReloc(0, 4, 3); - PE32.WriteName(File, ".bss"); - WriteReloc(File, 0, 5, 3); + PE32.WriteName(".bss"); + WriteReloc(0, 5, 3); - WR.Write32LE(File, 4); + WR.Write32LE(4); - WR.Close(File) + WR.Close END write; diff --git a/programs/develop/oberon07/Source/MSP430.ob07 b/programs/develop/oberon07/Source/MSP430.ob07 index 9b6ba4809..8a37320bf 100644 --- a/programs/develop/oberon07/Source/MSP430.ob07 +++ b/programs/develop/oberon07/Source/MSP430.ob07 @@ -421,8 +421,7 @@ END mov; PROCEDURE xchg (reg1, reg2: INTEGER); BEGIN Push(reg1); - Push(reg2); - Pop(reg1); + mov(reg1, reg2); Pop(reg2) END xchg; @@ -819,7 +818,7 @@ BEGIN Op2(opADD, reg2 * 256, reg1); drop - |IL.opADDL, IL.opADDR: + |IL.opADDC: IF param2 # 0 THEN UnOp(reg1); Op2(opADD, imm(param2), reg1) @@ -880,55 +879,42 @@ BEGIN cc := cond(opcode); next := cmd.next(COMMAND); - IF next.opcode = IL.opJE THEN + IF next.opcode = IL.opJNZ THEN jcc(cc, next.param1); cmd := next - ELSIF next.opcode = IL.opJNE THEN + ELSIF next.opcode = IL.opJZ THEN jcc(ORD(BITS(cc) / {0}), next.param1); cmd := next ELSE setcc(cc, GetAnyReg()) END - |IL.opNOP: + |IL.opNOP, IL.opAND, IL.opOR: |IL.opCODE: EmitWord(param2) - |IL.opACC: - IF (R.top # 0) OR (R.stk[0] # ACC) THEN - PushAll(0); - GetRegA; - Pop(ACC); - DEC(R.pushed) - END - |IL.opDROP: UnOp(reg1); drop - |IL.opJNZ: + |IL.opJNZ1: UnOp(reg1); Test(reg1); jcc(jne, param1) - |IL.opJZ: - UnOp(reg1); - Test(reg1); - jcc(je, param1) - |IL.opJG: UnOp(reg1); Test(reg1); jcc(jg, param1) - |IL.opJE: + |IL.opJNZ: UnOp(reg1); Test(reg1); jcc(jne, param1); drop - |IL.opJNE: + |IL.opJZ: UnOp(reg1); Test(reg1); jcc(je, param1); @@ -958,6 +944,11 @@ BEGIN drop; Op2(opMOV + bw(param2 = 1), src_x(param1, SR), dst_x(0, reg2)) + |IL.opCHKBYTE: + BinOp(reg1, reg2); + Op2(opCMP, imm(256), reg1); + jcc(jb, param1) + |IL.opCHKIDX: UnOp(reg1); Op2(opCMP, imm(param2), reg1); @@ -1079,7 +1070,7 @@ BEGIN Op2(opBIC, reg2 * 256, reg1); drop - |IL.opADDSL, IL.opADDSR: + |IL.opADDSC: UnOp(reg1); Op2(opBIS, imm(param2), reg1) @@ -1189,11 +1180,6 @@ BEGIN INCL(R.regs, reg1); ASSERT(REG.GetReg(R, reg1)) - |IL.opCHKBYTE: - BinOp(reg1, reg2); - Op2(opCMP, imm(256), reg1); - jcc(jb, param1) - |IL.opLSL, IL.opASR, IL.opROR, IL.opLSR: PushAll(2); CASE opcode OF @@ -1618,7 +1604,7 @@ END epilog; PROCEDURE CodeGen* (outname: ARRAY OF CHAR; target: INTEGER; options: PROG.OPTIONS); VAR - i, adr, heap, stack, TextSize, TypesSize, bits, n: INTEGER; + i, adr, heap, stack, TextSize, TypesSize, bits, n, val: INTEGER; Code, Data, Bss, Free: RECORD address, size: INTEGER END; @@ -1626,8 +1612,6 @@ VAR reloc: RELOC; - file: WR.FILE; - BEGIN IdxWords.src := NOWORD; IdxWords.dst := NOWORD; @@ -1687,10 +1671,11 @@ BEGIN reloc := RelList.first(RELOC); WHILE reloc # NIL DO adr := reloc.WordPtr.offset * 2; + val := reloc.WordPtr.val; CASE reloc.section OF - |RCODE: PutWord(LabelOffs(reloc.WordPtr.val) * 2, adr) - |RDATA: PutWord(reloc.WordPtr.val + Data.address, adr) - |RBSS: PutWord(reloc.WordPtr.val + Bss.address, adr) + |RCODE: PutWord(LabelOffs(val) * 2, adr) + |RDATA: PutWord(val + Data.address, adr) + |RBSS: PutWord(val + Bss.address, adr) END; reloc := reloc.next(RELOC) END; @@ -1733,13 +1718,13 @@ BEGIN PutWord(LabelOffs(IV[i]) * 2, adr) END; - file := WR.Create(outname); + WR.Create(outname); - HEX.Data(file, mem, Code.address, TextSize); - HEX.Data(file, mem, 10000H - IntVectorSize - TypesSize, IntVectorSize + TypesSize); - HEX.End(file); + HEX.Data(mem, Code.address, TextSize); + HEX.Data(mem, 10000H - IntVectorSize - TypesSize, IntVectorSize + TypesSize); + HEX.End; - WR.Close(file); + WR.Close; INC(TextSize, IntVectorSize + TypesSize); INC(Bss.size, minStackSize + RTL.VarSize); diff --git a/programs/develop/oberon07/Source/PARS.ob07 b/programs/develop/oberon07/Source/PARS.ob07 index eebcd1d84..a3f2078d7 100644 --- a/programs/develop/oberon07/Source/PARS.ob07 +++ b/programs/develop/oberon07/Source/PARS.ob07 @@ -34,7 +34,7 @@ TYPE EXPR* = RECORD obj*: INTEGER; - type*: PROG.TYPE_; + _type*: PROG._TYPE; value*: ARITH.VALUE; stproc*: INTEGER; readOnly*: BOOLEAN; @@ -44,7 +44,7 @@ TYPE STATPROC = PROCEDURE (parser: PARSER); EXPRPROC = PROCEDURE (parser: PARSER; VAR e: EXPR); - RETPROC = PROCEDURE (parser: PARSER; e: EXPR; t: PROG.TYPE_; pos: POSITION): BOOLEAN; + RETPROC = PROCEDURE (parser: PARSER; e: EXPR; t: PROG._TYPE; pos: POSITION): BOOLEAN; rPARSER = RECORD (C.ITEM) @@ -74,8 +74,6 @@ TYPE VAR - program*: PROG.PROGRAM; - parsers: C.COLLECTION; lines*, modules: INTEGER; @@ -133,10 +131,10 @@ VAR BEGIN SCAN.Next(parser.scanner, parser.lex); errno := parser.lex.error; - IF (errno = 0) & (TARGETS.CPU = TARGETS.cpuMSP430) THEN - IF parser.lex.sym = SCAN.lxFLOAT THEN + IF errno = 0 THEN + IF (TARGETS.RealSize = 0) & (parser.lex.sym = SCAN.lxFLOAT) THEN errno := -SCAN.lxERROR13 - ELSIF (parser.lex.sym = SCAN.lxCHAR) & (parser.lex.value.typ = ARITH.tWCHAR) THEN + ELSIF (TARGETS.BitDepth = 16) & (parser.lex.sym = SCAN.lxCHAR) & (parser.lex.value.typ = ARITH.tWCHAR) THEN errno := -SCAN.lxERROR10 END END; @@ -184,7 +182,6 @@ BEGIN |SCAN.lxSEMI: err := 24 |SCAN.lxRETURN: err := 38 |SCAN.lxMODULE: err := 21 - |SCAN.lxSTRING: err := 66 END; check1(FALSE, parser, err) @@ -227,7 +224,7 @@ BEGIN IF (parser.sym = SCAN.lxCOMMA) OR (parser.sym = SCAN.lxSEMI) THEN alias := FALSE; - unit := PROG.getUnit(program, name); + unit := PROG.getUnit(name); IF unit # NIL THEN check(unit.closed, pos, 31) @@ -250,7 +247,7 @@ BEGIN unit := parser2.unit; destroy(parser2) END; - IF unit = program.sysunit THEN + IF unit = PROG.program.sysunit THEN parser.unit.sysimport := TRUE END; ident.unit := unit @@ -350,7 +347,7 @@ BEGIN END ConstExpression; -PROCEDURE FieldList (parser: PARSER; rec: PROG.TYPE_); +PROCEDURE FieldList (parser: PARSER; rec: PROG._TYPE); VAR name: SCAN.IDENT; export: BOOLEAN; @@ -387,18 +384,18 @@ BEGIN END FieldList; -PROCEDURE FormalParameters (parser: PARSER; type: PROG.TYPE_); +PROCEDURE FormalParameters (parser: PARSER; _type: PROG._TYPE); VAR ident: PROG.IDENT; - PROCEDURE FPSection (parser: PARSER; type: PROG.TYPE_); + PROCEDURE FPSection (parser: PARSER; _type: PROG._TYPE); VAR ident: PROG.IDENT; exit: BOOLEAN; vPar: BOOLEAN; dim: INTEGER; - t0, t1: PROG.TYPE_; + t0, t1: PROG._TYPE; BEGIN vPar := parser.sym = SCAN.lxVAR; @@ -410,7 +407,7 @@ VAR exit := FALSE; WHILE (parser.sym = SCAN.lxIDENT) & ~exit DO - check1(PROG.addParam(type, parser.lex.ident, vPar), parser, 30); + check1(PROG.addParam(_type, parser.lex.ident, vPar), parser, 30); Next(parser); IF parser.sym = SCAN.lxCOMMA THEN ExpectSym(parser, SCAN.lxIDENT) @@ -427,17 +424,17 @@ VAR ident := QIdent(parser, FALSE); check1(ident.typ = PROG.idTYPE, parser, 68); - t0 := ident.type; + t0 := ident._type; t1 := t0; WHILE dim > 0 DO - t1 := PROG.enterType(program, PROG.tARRAY, -1, 0, parser.unit); + t1 := PROG.enterType(PROG.tARRAY, -1, 0, parser.unit); t1.base := t0; t0 := t1; DEC(dim) END; - PROG.setParams(type, t1); + PROG.setParams(_type, t1); Next(parser); exit := TRUE ELSE @@ -454,10 +451,10 @@ BEGIN Next(parser); IF (parser.sym = SCAN.lxVAR) OR (parser.sym = SCAN.lxIDENT) THEN - FPSection(parser, type); + FPSection(parser, _type); WHILE parser.sym = SCAN.lxSEMI DO Next(parser); - FPSection(parser, type) + FPSection(parser, _type) END END; @@ -468,12 +465,12 @@ BEGIN ExpectSym(parser, SCAN.lxIDENT); ident := QIdent(parser, FALSE); check1(ident.typ = PROG.idTYPE, parser, 68); - check1(~(ident.type.typ IN {PROG.tRECORD, PROG.tARRAY}), parser, 69); - check1( ~(ODD(type.call) & (ident.type.typ = PROG.tREAL)), parser, 113); - type.base := ident.type; + check1(~(ident._type.typ IN {PROG.tRECORD, PROG.tARRAY}), parser, 69); + check1( ~(ODD(_type.call) & (ident._type.typ = PROG.tREAL)), parser, 113); + _type.base := ident._type; Next(parser) ELSE - type.base := NIL + _type.base := NIL END END @@ -503,13 +500,15 @@ BEGIN sf := PROG.sf_linux ELSIF parser.lex.s = "code" THEN sf := PROG.sf_code + ELSIF parser.lex.s = "oberon" THEN + sf := PROG.sf_oberon ELSIF parser.lex.s = "noalign" THEN sf := PROG.sf_noalign ELSE check1(FALSE, parser, 124) END; - check1(sf IN program.sysflags, parser, 125); + check1(sf IN PROG.program.sysflags, parser, 125); IF proc THEN check1(sf IN PROG.proc_flags, parser, 123) @@ -532,6 +531,12 @@ BEGIN res := PROG.systemv |PROG.sf_code: res := PROG.code + |PROG.sf_oberon: + IF TARGETS.OS IN {TARGETS.osWIN32, TARGETS.osLINUX32, TARGETS.osKOS} THEN + res := PROG.default32 + ELSIF TARGETS.OS IN {TARGETS.osWIN64, TARGETS.osLINUX64} THEN + res := PROG.default64 + END |PROG.sf_windows: IF TARGETS.OS = TARGETS.osWIN32 THEN res := PROG.stdcall @@ -552,15 +557,33 @@ BEGIN END sysflag; -PROCEDURE procflag (parser: PARSER; VAR import: IL.IMPORT_PROC; isProc: BOOLEAN): INTEGER; +PROCEDURE procflag (parser: PARSER; VAR _import: IL.IMPORT_PROC; isProc: BOOLEAN): INTEGER; VAR call: INTEGER; dll, proc: SCAN.LEXSTR; pos: POSITION; -BEGIN - import := NIL; + PROCEDURE getStr (parser: PARSER; VAR name: SCAN.LEXSTR); + VAR + pos: POSITION; + str: ARITH.VALUE; + + BEGIN + getpos(parser, pos); + ConstExpression(parser, str); + IF str.typ = ARITH.tSTRING THEN + name := str.string(SCAN.IDENT).s + ELSIF str.typ = ARITH.tCHAR THEN + ARITH.charToStr(str, name) + ELSE + check(FALSE, pos, 117) + END + END getStr; + + +BEGIN + _import := NIL; IF parser.sym = SCAN.lxLSQUARE THEN getpos(parser, pos); @@ -572,34 +595,32 @@ BEGIN Next(parser); INC(call) END; - IF ~isProc THEN - checklex(parser, SCAN.lxRSQUARE) - END; - IF parser.sym = SCAN.lxCOMMA THEN - ExpectSym(parser, SCAN.lxSTRING); - dll := parser.lex.s; - STRINGS.UpCase(dll); - ExpectSym(parser, SCAN.lxCOMMA); - ExpectSym(parser, SCAN.lxSTRING); - proc := parser.lex.s; + + IF isProc & (parser.sym = SCAN.lxCOMMA) THEN Next(parser); - import := IL.AddImp(dll, proc) + getStr(parser, dll); + STRINGS.UpCase(dll); + checklex(parser, SCAN.lxCOMMA); + Next(parser); + getStr(parser, proc); + _import := IL.AddImp(dll, proc) END; + checklex(parser, SCAN.lxRSQUARE); Next(parser) ELSE CASE TARGETS.BitDepth OF |16: call := PROG.default16 - |32: IF TARGETS.target = TARGETS.STM32CM3 THEN - call := PROG.ccall - ELSE + |32: IF TARGETS.CPU = TARGETS.cpuX86 THEN call := PROG.default32 + ELSE + call := PROG.ccall END |64: call := PROG.default64 END END; - IF import # NIL THEN + IF _import # NIL THEN check(TARGETS.Import, pos, 70) END @@ -607,7 +628,7 @@ BEGIN END procflag; -PROCEDURE type (parser: PARSER; VAR t: PROG.TYPE_; flags: SET); +PROCEDURE _type (parser: PARSER; VAR t: PROG._TYPE; flags: SET); CONST comma = 0; closed = 1; @@ -619,11 +640,11 @@ VAR ident: PROG.IDENT; unit: PROG.UNIT; pos, pos2: POSITION; - fieldType: PROG.TYPE_; + fieldType: PROG._TYPE; baseIdent: SCAN.IDENT; a, b: INTEGER; RecFlag: INTEGER; - import: IL.IMPORT_PROC; + _import: IL.IMPORT_PROC; BEGIN unit := parser.unit; @@ -634,7 +655,7 @@ BEGIN IF ident # NIL THEN check1(ident.typ = PROG.idTYPE, parser, 49); - t := ident.type; + t := ident._type; check1(t # NIL, parser, 50); IF closed IN flags THEN check1(t.closed, parser, 50) @@ -656,13 +677,13 @@ BEGIN check(ARITH.check(arrLen), pos, 39); check(ARITH.getInt(arrLen) > 0, pos, 51); - t := PROG.enterType(program, PROG.tARRAY, -1, ARITH.getInt(arrLen), unit); + t := PROG.enterType(PROG.tARRAY, -1, ARITH.getInt(arrLen), unit); IF parser.sym = SCAN.lxCOMMA THEN - type(parser, t.base, {comma, closed}) + _type(parser, t.base, {comma, closed}) ELSIF parser.sym = SCAN.lxOF THEN Next(parser); - type(parser, t.base, {closed}) + _type(parser, t.base, {closed}) ELSE check1(FALSE, parser, 47) END; @@ -681,7 +702,7 @@ BEGIN getpos(parser, pos2); Next(parser); - t := PROG.enterType(program, PROG.tRECORD, 0, 0, unit); + t := PROG.enterType(PROG.tRECORD, 0, 0, unit); t.align := 1; IF parser.sym = SCAN.lxLSQUARE THEN @@ -698,7 +719,7 @@ BEGIN ExpectSym(parser, SCAN.lxIDENT); getpos(parser, pos); - type(parser, t.base, {closed}); + _type(parser, t.base, {closed}); check(t.base.typ IN {PROG.tRECORD, PROG.tPOINTER}, pos, 52); @@ -717,7 +738,7 @@ BEGIN t.align := t.base.align END ELSE - t.base := program.stTypes.tANYREC + t.base := PROG.program.stTypes.tANYREC END; WHILE parser.sym = SCAN.lxIDENT DO @@ -726,7 +747,7 @@ BEGIN ASSERT(parser.sym = SCAN.lxCOLON); Next(parser); - type(parser, fieldType, {closed}); + _type(parser, fieldType, {closed}); check(PROG.setFields(t, fieldType), pos2, 104); IF (fieldType.align > t.align) & ~t.noalign THEN @@ -756,7 +777,7 @@ BEGIN ExpectSym(parser, SCAN.lxTO); Next(parser); - t := PROG.enterType(program, PROG.tPOINTER, TARGETS.AdrSize, 0, unit); + t := PROG.enterType(PROG.tPOINTER, TARGETS.AdrSize, 0, unit); t.align := TARGETS.AdrSize; getpos(parser, pos); @@ -765,7 +786,7 @@ BEGIN baseIdent := parser.lex.ident END; - type(parser, t.base, {forward}); + _type(parser, t.base, {forward}); IF t.base # NIL THEN check(t.base.typ = PROG.tRECORD, pos, 58) @@ -775,15 +796,15 @@ BEGIN ELSIF parser.sym = SCAN.lxPROCEDURE THEN NextPos(parser, pos); - t := PROG.enterType(program, PROG.tPROCEDURE, TARGETS.AdrSize, 0, unit); + t := PROG.enterType(PROG.tPROCEDURE, TARGETS.AdrSize, 0, unit); t.align := TARGETS.AdrSize; - t.call := procflag(parser, import, FALSE); + t.call := procflag(parser, _import, FALSE); FormalParameters(parser, t) ELSE check1(FALSE, parser, 49) END -END type; +END _type; PROCEDURE IdentDef (parser: PARSER; typ: INTEGER; VAR name: SCAN.IDENT): PROG.IDENT; @@ -811,14 +832,14 @@ BEGIN END IdentDef; -PROCEDURE ConstTypeDeclaration (parser: PARSER; const: BOOLEAN); +PROCEDURE ConstTypeDeclaration (parser: PARSER; _const: BOOLEAN); VAR ident: PROG.IDENT; name: SCAN.IDENT; pos: POSITION; BEGIN - IF const THEN + IF _const THEN ident := IdentDef(parser, PROG.idNONE, name) ELSE ident := IdentDef(parser, PROG.idTYPE, name) @@ -827,7 +848,7 @@ BEGIN checklex(parser, SCAN.lxEQ); NextPos(parser, pos); - IF const THEN + IF _const THEN ConstExpression(parser, ident.value); IF ident.value.typ = ARITH.tINTEGER THEN check(ARITH.check(ident.value), pos, 39) @@ -835,9 +856,9 @@ BEGIN check(ARITH.check(ident.value), pos, 40) END; ident.typ := PROG.idCONST; - ident.type := PROG.getType(program, ident.value.typ) + ident._type := PROG.getType(ident.value.typ) ELSE - type(parser, ident.type, {}) + _type(parser, ident._type, {}) END; checklex(parser, SCAN.lxSEMI); @@ -850,7 +871,7 @@ PROCEDURE VarDeclaration (parser: PARSER); VAR ident: PROG.IDENT; name: SCAN.IDENT; - t: PROG.TYPE_; + t: PROG._TYPE; BEGIN @@ -861,7 +882,7 @@ BEGIN ExpectSym(parser, SCAN.lxIDENT) ELSIF parser.sym = SCAN.lxCOLON THEN Next(parser); - type(parser, t, {}); + _type(parser, t, {}); PROG.setVarsType(parser.unit, t); checklex(parser, SCAN.lxSEMI); Next(parser) @@ -895,8 +916,8 @@ VAR label: INTEGER; enter: IL.COMMAND; call: INTEGER; - t: PROG.TYPE_; - import: IL.IMPORT_PROC; + t: PROG._TYPE; + _import: IL.IMPORT_PROC; endmod, b: BOOLEAN; fparams: SET; variables: LISTS.LIST; @@ -912,24 +933,27 @@ VAR unit := parser.unit; - call := procflag(parser, import, TRUE); + call := procflag(parser, _import, TRUE); getpos(parser, pos); pos1 := pos; checklex(parser, SCAN.lxIDENT); - IF import # NIL THEN + IF _import # NIL THEN proc := IdentDef(parser, PROG.idIMP, name); - proc.import := import; - program.procs.last(PROG.PROC).import := import + proc._import := _import; + IF _import.name = "" THEN + _import.name := name.s + END; + PROG.program.procs.last(PROG.PROC)._import := _import ELSE proc := IdentDef(parser, PROG.idPROC, name) END; check(PROG.openScope(unit, proc.proc), pos, 116); - proc.type := PROG.enterType(program, PROG.tPROCEDURE, TARGETS.AdrSize, 0, unit); - t := proc.type; + proc._type := PROG.enterType(PROG.tPROCEDURE, TARGETS.AdrSize, 0, unit); + t := proc._type; t.align := TARGETS.AdrSize; t.call := call; @@ -959,7 +983,7 @@ VAR WHILE param # NIL DO ident := PROG.addIdent(unit, param.name, PROG.idPARAM); ASSERT(ident # NIL); - ident.type := param.type; + ident._type := param._type; ident.offset := param.offset; IF param.vPar THEN ident.typ := PROG.idVPAR @@ -967,7 +991,7 @@ VAR param := param.next(PROG.PARAM) END; - IF import = NIL THEN + IF _import = NIL THEN label := IL.NewLabel(); proc.proc.label := label; proc.proc.used := handler; @@ -983,10 +1007,11 @@ VAR getpos(parser, pos2); ConstExpression(parser, code); check(code.typ = ARITH.tINTEGER, pos2, 43); - IF TARGETS.CPU IN {TARGETS.cpuX86, TARGETS.cpuAMD64} THEN - check(ARITH.range(code, 0, 255), pos2, 42) - ELSIF TARGETS.CPU = TARGETS.cpuTHUMB THEN - check(ARITH.range(code, 0, 65535), pos2, 110) + IF TARGETS.WordSize > TARGETS.InstrSize THEN + CASE TARGETS.InstrSize OF + |1: check(ARITH.range(code, 0, 255), pos, 42) + |2: check(ARITH.range(code, 0, 65535), pos, 110) + END END; IL.AddCmd(IL.opCODE, ARITH.getInt(code)); comma := parser.sym = SCAN.lxCOMMA; @@ -1001,7 +1026,7 @@ VAR checklex(parser, SCAN.lxSEMI); Next(parser); - IF import = NIL THEN + IF _import = NIL THEN IF parser.main & proc.export & TARGETS.Dll THEN IF TARGETS.target = TARGETS.KolibriOSDLL THEN @@ -1015,13 +1040,13 @@ VAR b := DeclarationSequence(parser) END; - program.locsize := 0; + PROG.ResetLocSize; IF call IN {PROG._win64, PROG.win64} THEN - fparams := PROG.getFloatParamsPos(proc.type, 3, int, flt); - enter := IL.Enter(label, LSL(ORD(fparams), 5) + MIN(proc.type.parSize, 4)) + fparams := PROG.getFloatParamsPos(proc._type, 3, int, flt); + enter := IL.Enter(label, LSL(ORD(fparams), 5) + MIN(proc._type.parSize, 4)) ELSIF call IN {PROG._systemv, PROG.systemv} THEN - fparams := PROG.getFloatParamsPos(proc.type, PROG.MAXSYSVPARAM - 1, int, flt); - enter := IL.Enter(label, -(LSL(ORD(fparams), 5) + proc.type.parSize)) + fparams := PROG.getFloatParamsPos(proc._type, PROG.MAXSYSVPARAM - 1, int, flt); + enter := IL.Enter(label, -(LSL(ORD(fparams), 5) + proc._type.parSize)) ELSIF codeProc THEN ELSE @@ -1042,42 +1067,48 @@ VAR END; IF ~codeProc THEN - proc.proc.leave := IL.Leave(t.base # NIL, (t.base # NIL) & (t.base.typ = PROG.tREAL), program.locsize, + proc.proc.leave := IL.Leave(t.base # NIL, (t.base # NIL) & (t.base.typ = PROG.tREAL), PROG.program.locsize, t.parSize * ORD((t.call IN PROG.callee_clean_up) OR (t.call IN {PROG.systemv, PROG._systemv}))); - enter.param2 := program.locsize; + enter.param2 := PROG.program.locsize; checklex(parser, SCAN.lxEND) ELSE proc.proc.leave := IL.LeaveC() END; IF TARGETS.CPU = TARGETS.cpuMSP430 THEN - check((enter.param2 * ORD(~codeProc) + proc.type.parSize) * 2 + 16 < program.options.ram, pos1, 63) + check((enter.param2 * ORD(~codeProc) + proc._type.parSize) * 2 + 16 < PROG.program.options.ram, pos1, 63) END END; IF parser.sym = SCAN.lxEND THEN - ExpectSym(parser, SCAN.lxIDENT); - getpos(parser, pos); - endname := parser.lex.ident; - IF ~codeProc & (import = NIL) THEN - check(endname = name, pos, 60); - ExpectSym(parser, SCAN.lxSEMI); - Next(parser) - ELSE - IF endname = parser.unit.name THEN - ExpectSym(parser, SCAN.lxPOINT); - Next(parser); - endmod := TRUE - ELSIF endname = name THEN + Next(parser); + IF parser.sym = SCAN.lxIDENT THEN + getpos(parser, pos); + endname := parser.lex.ident; + IF ~codeProc & (_import = NIL) THEN + check(endname = name, pos, 60); ExpectSym(parser, SCAN.lxSEMI); Next(parser) ELSE - error(pos, 60) + IF endname = parser.unit.name THEN + ExpectSym(parser, SCAN.lxPOINT); + Next(parser); + endmod := TRUE + ELSIF endname = name THEN + ExpectSym(parser, SCAN.lxSEMI); + Next(parser) + ELSE + error(pos, 60) + END END + ELSIF parser.sym = SCAN.lxSEMI THEN + Next(parser) + ELSE + checklex(parser, SCAN.lxIDENT) END END; - IF ~codeProc & (import = NIL) THEN + IF ~codeProc & (_import = NIL) THEN variables := LISTS.create(NIL); ELSE variables := NIL @@ -1085,7 +1116,7 @@ VAR PROG.closeScope(unit, variables); - IF ~codeProc & (import = NIL) THEN + IF ~codeProc & (_import = NIL) THEN enter.variables := variables END @@ -1157,7 +1188,7 @@ BEGIN check1(parser.lex.s = parser.modname, parser, 23) END; - unit := PROG.newUnit(program, parser.lex.ident); + unit := PROG.newUnit(parser.lex.ident); parser.unit := unit; @@ -1171,15 +1202,17 @@ BEGIN INC(modules); CONSOLE.String("compiling "); - IF TARGETS.CPU IN {TARGETS.cpuTHUMB, TARGETS.cpuMSP430} THEN - CONSOLE.String("("); CONSOLE.Int(modules); CONSOLE.String(") ") - END; + CONSOLE.String("("); CONSOLE.Int(modules); CONSOLE.String(") "); CONSOLE.String(unit.name.s); IF parser.unit.sysimport THEN CONSOLE.String(" (SYSTEM)") END; CONSOLE.Ln; + IF TARGETS.CPU IN {TARGETS.cpuX86, TARGETS.cpuAMD64} THEN + IL.fname(parser.fname) + END; + label := IL.NewLabel(); IL.AddJmpCmd(IL.opJMP, label); @@ -1189,9 +1222,7 @@ BEGIN IL.SetLabel(errlabel); IL.StrAdr(name); IL.Param1; - IF TARGETS.CPU IN {TARGETS.cpuTHUMB, TARGETS.cpuMSP430} THEN - IL.AddCmd(IL.opPUSHC, modules) - END; + IL.AddCmd(IL.opPUSHC, modules); IL.AddCmd0(IL.opERR); FOR errno := 1 TO LEN(IL.codes.errlabels) - 1 DO @@ -1285,7 +1316,7 @@ END create; PROCEDURE init* (options: PROG.OPTIONS); BEGIN - program := PROG.create(options); + PROG.create(options); parsers := C.create(); lines := 0; modules := 0 diff --git a/programs/develop/oberon07/Source/PE32.ob07 b/programs/develop/oberon07/Source/PE32.ob07 index 32d1fc17e..30a4ed3b9 100644 --- a/programs/develop/oberon07/Source/PE32.ob07 +++ b/programs/develop/oberon07/Source/PE32.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018-2019, Anton Krotov + Copyright (c) 2018-2020, Anton Krotov All rights reserved. *) @@ -102,15 +102,6 @@ TYPE END; - IMAGE_NT_HEADERS = RECORD - - Signature: ARRAY 4 OF BYTE; - FileHeader: IMAGE_FILE_HEADER; - OptionalHeader: IMAGE_OPTIONAL_HEADER - - END; - - IMAGE_SECTION_HEADER* = RECORD Name*: NAME; @@ -147,35 +138,33 @@ TYPE END; - VIRTUAL_ADDR = RECORD + VIRTUAL_ADDR* = RECORD - Code, Data, Bss, Import: INTEGER + Code*, Data*, Bss*, Import*: INTEGER END; - FILE = WR.FILE; - - VAR + Signature: ARRAY 4 OF BYTE; + FileHeader: IMAGE_FILE_HEADER; + OptionalHeader: IMAGE_OPTIONAL_HEADER; + msdos: ARRAY 128 OF BYTE; - PEHeader: IMAGE_NT_HEADERS; SectionHeaders: ARRAY 16 OF IMAGE_SECTION_HEADER; - Relocations: LISTS.LIST; - bit64: BOOLEAN; libcnt: INTEGER; SizeOfWord: INTEGER; -PROCEDURE Export (program: BIN.PROGRAM; DataRVA: INTEGER; VAR ExportDir: IMAGE_EXPORT_DIRECTORY): INTEGER; +PROCEDURE Export (program: BIN.PROGRAM; name: INTEGER; VAR ExportDir: IMAGE_EXPORT_DIRECTORY): INTEGER; BEGIN ExportDir.Characteristics := 0; - ExportDir.TimeDateStamp := PEHeader.FileHeader.TimeDateStamp; + ExportDir.TimeDateStamp := FileHeader.TimeDateStamp; ExportDir.MajorVersion := 0X; ExportDir.MinorVersion := 0X; - ExportDir.Name := program.modname + DataRVA; + ExportDir.Name := name; ExportDir.Base := 0; ExportDir.NumberOfFunctions := LISTS.count(program.exp_list); ExportDir.NumberOfNames := ExportDir.NumberOfFunctions; @@ -187,27 +176,17 @@ BEGIN END Export; -PROCEDURE align (n, _align: INTEGER): INTEGER; -BEGIN - IF n MOD _align # 0 THEN - n := n + _align - (n MOD _align) - END - - RETURN n -END align; - - PROCEDURE GetProcCount (lib: BIN.IMPRT): INTEGER; VAR - import: BIN.IMPRT; - res: INTEGER; + imp: BIN.IMPRT; + res: INTEGER; BEGIN res := 0; - import := lib.next(BIN.IMPRT); - WHILE (import # NIL) & (import.label # 0) DO + imp := lib.next(BIN.IMPRT); + WHILE (imp # NIL) & (imp.label # 0) DO INC(res); - import := import.next(BIN.IMPRT) + imp := imp.next(BIN.IMPRT) END RETURN res @@ -216,7 +195,7 @@ END GetProcCount; PROCEDURE GetImportSize (imp_list: LISTS.LIST): INTEGER; VAR - import: BIN.IMPRT; + imp: BIN.IMPRT; proccnt: INTEGER; procoffs: INTEGER; OriginalCurrentThunk, @@ -225,86 +204,86 @@ VAR BEGIN libcnt := 0; proccnt := 0; - import := imp_list.first(BIN.IMPRT); - WHILE import # NIL DO - IF import.label = 0 THEN + imp := imp_list.first(BIN.IMPRT); + WHILE imp # NIL DO + IF imp.label = 0 THEN INC(libcnt) ELSE INC(proccnt) END; - import := import.next(BIN.IMPRT) + imp := imp.next(BIN.IMPRT) END; procoffs := 0; - import := imp_list.first(BIN.IMPRT); - WHILE import # NIL DO - IF import.label = 0 THEN - import.OriginalFirstThunk := procoffs; - import.FirstThunk := procoffs + (GetProcCount(import) + 1); - OriginalCurrentThunk := import.OriginalFirstThunk; - CurrentThunk := import.FirstThunk; - procoffs := procoffs + (GetProcCount(import) + 1) * 2 + imp := imp_list.first(BIN.IMPRT); + WHILE imp # NIL DO + IF imp.label = 0 THEN + imp.OriginalFirstThunk := procoffs; + imp.FirstThunk := procoffs + (GetProcCount(imp) + 1); + OriginalCurrentThunk := imp.OriginalFirstThunk; + CurrentThunk := imp.FirstThunk; + INC(procoffs, (GetProcCount(imp) + 1) * 2) ELSE - import.OriginalFirstThunk := OriginalCurrentThunk; - import.FirstThunk := CurrentThunk; + imp.OriginalFirstThunk := OriginalCurrentThunk; + imp.FirstThunk := CurrentThunk; INC(OriginalCurrentThunk); INC(CurrentThunk) END; - import := import.next(BIN.IMPRT) + imp := imp.next(BIN.IMPRT) END RETURN (libcnt + 1) * 5 * SIZE_OF_DWORD + (proccnt + libcnt) * 2 * SizeOfWord END GetImportSize; -PROCEDURE fixup (program: BIN.PROGRAM; Address: VIRTUAL_ADDR); +PROCEDURE fixup* (program: BIN.PROGRAM; Address: VIRTUAL_ADDR; amd64: BOOLEAN); VAR reloc: BIN.RELOC; iproc: BIN.IMPRT; code: CHL.BYTELIST; - L, delta, delta0, AdrImp: INTEGER; + L, delta, delta0, AdrImp, offset: INTEGER; BEGIN AdrImp := Address.Import + (libcnt + 1) * 5 * SIZE_OF_DWORD; code := program.code; reloc := program.rel_list.first(BIN.RELOC); - delta0 := 3 - 7 * ORD(bit64); + delta0 := 3 - 7 * ORD(amd64) - Address.Code; WHILE reloc # NIL DO - L := BIN.get32le(code, reloc.offset); - delta := delta0 - reloc.offset - Address.Code; + offset := reloc.offset; + L := BIN.get32le(code, offset); + delta := delta0 - offset; CASE reloc.opcode OF - |BIN.PICDATA: - BIN.put32le(code, reloc.offset, L + Address.Data + delta) + INC(delta, L + Address.Data) |BIN.PICCODE: - BIN.put32le(code, reloc.offset, BIN.GetLabel(program, L) + Address.Code + delta) + INC(delta, BIN.GetLabel(program, L) + Address.Code) |BIN.PICBSS: - BIN.put32le(code, reloc.offset, L + Address.Bss + delta) + INC(delta, L + Address.Bss) |BIN.PICIMP: - iproc := BIN.GetIProc(program, L); - BIN.put32le(code, reloc.offset, iproc.FirstThunk * SizeOfWord + AdrImp + delta) - + iproc := BIN.GetIProc(program, L); + INC(delta, iproc.FirstThunk * SizeOfWord + AdrImp) END; + BIN.put32le(code, offset, delta); reloc := reloc.next(BIN.RELOC) END END fixup; -PROCEDURE WriteWord (file: FILE; w: WORD); +PROCEDURE WriteWord (w: WORD); BEGIN - WR.Write16LE(file, ORD(w)) + WR.Write16LE(ORD(w)) END WriteWord; -PROCEDURE WriteName* (File: FILE; name: NAME); +PROCEDURE WriteName* (name: NAME); VAR i, nameLen: INTEGER; @@ -312,19 +291,19 @@ BEGIN nameLen := LENGTH(name); FOR i := 0 TO nameLen - 1 DO - WR.WriteByte(File, ORD(name[i])) + WR.WriteByte(ORD(name[i])) END; i := LEN(name) - nameLen; WHILE i > 0 DO - WR.WriteByte(File, 0); + WR.WriteByte(0); DEC(i) END END WriteName; -PROCEDURE WriteSectionHeader* (file: FILE; h: IMAGE_SECTION_HEADER); +PROCEDURE WriteSectionHeader* (h: IMAGE_SECTION_HEADER); VAR i, nameLen: INTEGER; @@ -332,50 +311,50 @@ BEGIN nameLen := LENGTH(h.Name); FOR i := 0 TO nameLen - 1 DO - WR.WriteByte(file, ORD(h.Name[i])) + WR.WriteByte(ORD(h.Name[i])) END; i := LEN(h.Name) - nameLen; WHILE i > 0 DO - WR.WriteByte(file, 0); + WR.WriteByte(0); DEC(i) END; - WR.Write32LE(file, h.VirtualSize); - WR.Write32LE(file, h.VirtualAddress); - WR.Write32LE(file, h.SizeOfRawData); - WR.Write32LE(file, h.PointerToRawData); - WR.Write32LE(file, h.PointerToRelocations); - WR.Write32LE(file, h.PointerToLinenumbers); + WR.Write32LE(h.VirtualSize); + WR.Write32LE(h.VirtualAddress); + WR.Write32LE(h.SizeOfRawData); + WR.Write32LE(h.PointerToRawData); + WR.Write32LE(h.PointerToRelocations); + WR.Write32LE(h.PointerToLinenumbers); - WriteWord(file, h.NumberOfRelocations); - WriteWord(file, h.NumberOfLinenumbers); + WriteWord(h.NumberOfRelocations); + WriteWord(h.NumberOfLinenumbers); - WR.Write32LE(file, h.Characteristics) + WR.Write32LE(h.Characteristics) END WriteSectionHeader; -PROCEDURE WriteFileHeader* (file: FILE; h: IMAGE_FILE_HEADER); +PROCEDURE WriteFileHeader* (h: IMAGE_FILE_HEADER); BEGIN - WriteWord(file, h.Machine); - WriteWord(file, h.NumberOfSections); + WriteWord(h.Machine); + WriteWord(h.NumberOfSections); - WR.Write32LE(file, h.TimeDateStamp); - WR.Write32LE(file, h.PointerToSymbolTable); - WR.Write32LE(file, h.NumberOfSymbols); + WR.Write32LE(h.TimeDateStamp); + WR.Write32LE(h.PointerToSymbolTable); + WR.Write32LE(h.NumberOfSymbols); - WriteWord(file, h.SizeOfOptionalHeader); - WriteWord(file, h.Characteristics) + WriteWord(h.SizeOfOptionalHeader); + WriteWord(h.Characteristics) END WriteFileHeader; PROCEDURE write* (program: BIN.PROGRAM; FileName: ARRAY OF CHAR; console, dll, amd64: BOOLEAN); VAR - i, n: INTEGER; + i, n, temp: INTEGER; Size: RECORD - Code, Data, Bss, Stack, Import, Reloc, Export: INTEGER + Code, Data, Bss, Import, Reloc, Export: INTEGER END; @@ -383,108 +362,100 @@ VAR Address: VIRTUAL_ADDR; - File: FILE; - - import: BIN.IMPRT; + _import: BIN.IMPRT; ImportTable: CHL.INTLIST; ExportDir: IMAGE_EXPORT_DIRECTORY; export: BIN.EXPRT; - PROCEDURE WriteExportDir (file: FILE; e: IMAGE_EXPORT_DIRECTORY); + PROCEDURE WriteExportDir (e: IMAGE_EXPORT_DIRECTORY); BEGIN - WR.Write32LE(file, e.Characteristics); - WR.Write32LE(file, e.TimeDateStamp); + WR.Write32LE(e.Characteristics); + WR.Write32LE(e.TimeDateStamp); - WriteWord(file, e.MajorVersion); - WriteWord(file, e.MinorVersion); + WriteWord(e.MajorVersion); + WriteWord(e.MinorVersion); - WR.Write32LE(file, e.Name); - WR.Write32LE(file, e.Base); - WR.Write32LE(file, e.NumberOfFunctions); - WR.Write32LE(file, e.NumberOfNames); - WR.Write32LE(file, e.AddressOfFunctions); - WR.Write32LE(file, e.AddressOfNames); - WR.Write32LE(file, e.AddressOfNameOrdinals) + WR.Write32LE(e.Name); + WR.Write32LE(e.Base); + WR.Write32LE(e.NumberOfFunctions); + WR.Write32LE(e.NumberOfNames); + WR.Write32LE(e.AddressOfFunctions); + WR.Write32LE(e.AddressOfNames); + WR.Write32LE(e.AddressOfNameOrdinals) END WriteExportDir; - PROCEDURE WriteOptHeader (file: FILE; h: IMAGE_OPTIONAL_HEADER); + PROCEDURE WriteOptHeader (h: IMAGE_OPTIONAL_HEADER; amd64: BOOLEAN); VAR i: INTEGER; BEGIN - WriteWord(file, h.Magic); + WriteWord(h.Magic); - WR.WriteByte(file, h.MajorLinkerVersion); - WR.WriteByte(file, h.MinorLinkerVersion); + WR.WriteByte(h.MajorLinkerVersion); + WR.WriteByte(h.MinorLinkerVersion); - WR.Write32LE(file, h.SizeOfCode); - WR.Write32LE(file, h.SizeOfInitializedData); - WR.Write32LE(file, h.SizeOfUninitializedData); - WR.Write32LE(file, h.AddressOfEntryPoint); - WR.Write32LE(file, h.BaseOfCode); + WR.Write32LE(h.SizeOfCode); + WR.Write32LE(h.SizeOfInitializedData); + WR.Write32LE(h.SizeOfUninitializedData); + WR.Write32LE(h.AddressOfEntryPoint); + WR.Write32LE(h.BaseOfCode); - IF bit64 THEN - WR.Write64LE(file, h.ImageBase) + IF amd64 THEN + WR.Write64LE(h.ImageBase) ELSE - WR.Write32LE(file, h.BaseOfData); - WR.Write32LE(file, h.ImageBase) + WR.Write32LE(h.BaseOfData); + WR.Write32LE(h.ImageBase) END; - WR.Write32LE(file, h.SectionAlignment); - WR.Write32LE(file, h.FileAlignment); + WR.Write32LE(h.SectionAlignment); + WR.Write32LE(h.FileAlignment); - WriteWord(file, h.MajorOperatingSystemVersion); - WriteWord(file, h.MinorOperatingSystemVersion); - WriteWord(file, h.MajorImageVersion); - WriteWord(file, h.MinorImageVersion); - WriteWord(file, h.MajorSubsystemVersion); - WriteWord(file, h.MinorSubsystemVersion); + WriteWord(h.MajorOperatingSystemVersion); + WriteWord(h.MinorOperatingSystemVersion); + WriteWord(h.MajorImageVersion); + WriteWord(h.MinorImageVersion); + WriteWord(h.MajorSubsystemVersion); + WriteWord(h.MinorSubsystemVersion); - WR.Write32LE(file, h.Win32VersionValue); - WR.Write32LE(file, h.SizeOfImage); - WR.Write32LE(file, h.SizeOfHeaders); - WR.Write32LE(file, h.CheckSum); + WR.Write32LE(h.Win32VersionValue); + WR.Write32LE(h.SizeOfImage); + WR.Write32LE(h.SizeOfHeaders); + WR.Write32LE(h.CheckSum); - WriteWord(file, h.Subsystem); - WriteWord(file, h.DllCharacteristics); + WriteWord(h.Subsystem); + WriteWord(h.DllCharacteristics); - IF bit64 THEN - WR.Write64LE(file, h.SizeOfStackReserve); - WR.Write64LE(file, h.SizeOfStackCommit); - WR.Write64LE(file, h.SizeOfHeapReserve); - WR.Write64LE(file, h.SizeOfHeapCommit) + IF amd64 THEN + WR.Write64LE(h.SizeOfStackReserve); + WR.Write64LE(h.SizeOfStackCommit); + WR.Write64LE(h.SizeOfHeapReserve); + WR.Write64LE(h.SizeOfHeapCommit) ELSE - WR.Write32LE(file, h.SizeOfStackReserve); - WR.Write32LE(file, h.SizeOfStackCommit); - WR.Write32LE(file, h.SizeOfHeapReserve); - WR.Write32LE(file, h.SizeOfHeapCommit) + WR.Write32LE(h.SizeOfStackReserve); + WR.Write32LE(h.SizeOfStackCommit); + WR.Write32LE(h.SizeOfHeapReserve); + WR.Write32LE(h.SizeOfHeapCommit) END; - WR.Write32LE(file, h.LoaderFlags); - WR.Write32LE(file, h.NumberOfRvaAndSizes); + WR.Write32LE(h.LoaderFlags); + WR.Write32LE(h.NumberOfRvaAndSizes); FOR i := 0 TO LEN(h.DataDirectory) - 1 DO - WR.Write32LE(file, h.DataDirectory[i].VirtualAddress); - WR.Write32LE(file, h.DataDirectory[i].Size) + WR.Write32LE(h.DataDirectory[i].VirtualAddress); + WR.Write32LE(h.DataDirectory[i].Size) END END WriteOptHeader; - PROCEDURE WritePEHeader (file: FILE; h: IMAGE_NT_HEADERS); - BEGIN - WR.Write(file, h.Signature, LEN(h.Signature)); - WriteFileHeader(file, h.FileHeader); - WriteOptHeader(file, h.OptionalHeader) - END WritePEHeader; - - - PROCEDURE InitSection (VAR section: IMAGE_SECTION_HEADER; Name: NAME; Characteristics: DWORD); + PROCEDURE InitSection (VAR section: IMAGE_SECTION_HEADER; Name: NAME; VirtualSize: INTEGER; Characteristics: DWORD); BEGIN section.Name := Name; + section.VirtualSize := VirtualSize; + section.SizeOfRawData := WR.align(VirtualSize, FileAlignment); section.PointerToRelocations := 0; section.PointerToLinenumbers := 0; section.NumberOfRelocations := 0X; @@ -494,14 +465,11 @@ VAR BEGIN - bit64 := amd64; - SizeOfWord := SIZE_OF_DWORD * (ORD(bit64) + 1); - Relocations := LISTS.create(NIL); + SizeOfWord := SIZE_OF_DWORD * (ORD(amd64) + 1); Size.Code := CHL.Length(program.code); Size.Data := CHL.Length(program.data); Size.Bss := program.bss; - Size.Stack := program.stack; IF dll THEN BaseAddress := 10000000H @@ -509,123 +477,109 @@ BEGIN BaseAddress := 400000H END; - PEHeader.Signature[0] := 50H; - PEHeader.Signature[1] := 45H; - PEHeader.Signature[2] := 0; - PEHeader.Signature[3] := 0; + Signature[0] := 50H; + Signature[1] := 45H; + Signature[2] := 0; + Signature[3] := 0; IF amd64 THEN - PEHeader.FileHeader.Machine := 08664X + FileHeader.Machine := 08664X ELSE - PEHeader.FileHeader.Machine := 014CX + FileHeader.Machine := 014CX END; - PEHeader.FileHeader.NumberOfSections := WCHR(4 + ORD(dll)); + FileHeader.NumberOfSections := WCHR(4 + ORD(dll)); - PEHeader.FileHeader.TimeDateStamp := UTILS.UnixTime(); - PEHeader.FileHeader.PointerToSymbolTable := 0H; - PEHeader.FileHeader.NumberOfSymbols := 0H; - PEHeader.FileHeader.SizeOfOptionalHeader := WCHR(0E0H + 10H * ORD(amd64)); - PEHeader.FileHeader.Characteristics := WCHR(010EH + (20H - 100H) * ORD(amd64) + 2000H * ORD(dll)); + FileHeader.TimeDateStamp := UTILS.UnixTime(); + FileHeader.PointerToSymbolTable := 0H; + FileHeader.NumberOfSymbols := 0H; + FileHeader.SizeOfOptionalHeader := WCHR(0E0H + 10H * ORD(amd64)); + FileHeader.Characteristics := WCHR(010EH + (20H - 100H) * ORD(amd64) + 2000H * ORD(dll)); - PEHeader.OptionalHeader.Magic := WCHR(010BH + 100H * ORD(amd64)); - PEHeader.OptionalHeader.MajorLinkerVersion := UTILS.vMajor; - PEHeader.OptionalHeader.MinorLinkerVersion := UTILS.vMinor; - PEHeader.OptionalHeader.SizeOfCode := align(Size.Code, FileAlignment); - PEHeader.OptionalHeader.SizeOfInitializedData := 0; - PEHeader.OptionalHeader.SizeOfUninitializedData := 0; - PEHeader.OptionalHeader.AddressOfEntryPoint := SectionAlignment; - PEHeader.OptionalHeader.BaseOfCode := SectionAlignment; - PEHeader.OptionalHeader.BaseOfData := PEHeader.OptionalHeader.BaseOfCode + align(Size.Code, SectionAlignment); - PEHeader.OptionalHeader.ImageBase := BaseAddress; - PEHeader.OptionalHeader.SectionAlignment := SectionAlignment; - PEHeader.OptionalHeader.FileAlignment := FileAlignment; - PEHeader.OptionalHeader.MajorOperatingSystemVersion := 1X; - PEHeader.OptionalHeader.MinorOperatingSystemVersion := 0X; - PEHeader.OptionalHeader.MajorImageVersion := 0X; - PEHeader.OptionalHeader.MinorImageVersion := 0X; - PEHeader.OptionalHeader.MajorSubsystemVersion := 4X; - PEHeader.OptionalHeader.MinorSubsystemVersion := 0X; - PEHeader.OptionalHeader.Win32VersionValue := 0H; - PEHeader.OptionalHeader.SizeOfImage := SectionAlignment; - PEHeader.OptionalHeader.SizeOfHeaders := 400H; - PEHeader.OptionalHeader.CheckSum := 0; - PEHeader.OptionalHeader.Subsystem := WCHR((2 + ORD(console)) * ORD(~dll)); - PEHeader.OptionalHeader.DllCharacteristics := 0040X; - PEHeader.OptionalHeader.SizeOfStackReserve := Size.Stack; - PEHeader.OptionalHeader.SizeOfStackCommit := Size.Stack DIV 16; - PEHeader.OptionalHeader.SizeOfHeapReserve := 100000H; - PEHeader.OptionalHeader.SizeOfHeapCommit := 10000H; - PEHeader.OptionalHeader.LoaderFlags := 0; - PEHeader.OptionalHeader.NumberOfRvaAndSizes := IMAGE_NUMBEROF_DIRECTORY_ENTRIES; + OptionalHeader.Magic := WCHR(010BH + 100H * ORD(amd64)); + OptionalHeader.MajorLinkerVersion := UTILS.vMajor; + OptionalHeader.MinorLinkerVersion := UTILS.vMinor; + OptionalHeader.SizeOfCode := WR.align(Size.Code, FileAlignment); + OptionalHeader.SizeOfInitializedData := 0; + OptionalHeader.SizeOfUninitializedData := 0; + OptionalHeader.AddressOfEntryPoint := SectionAlignment; + OptionalHeader.BaseOfCode := SectionAlignment; + OptionalHeader.BaseOfData := OptionalHeader.BaseOfCode + WR.align(Size.Code, SectionAlignment); + OptionalHeader.ImageBase := BaseAddress; + OptionalHeader.SectionAlignment := SectionAlignment; + OptionalHeader.FileAlignment := FileAlignment; + OptionalHeader.MajorOperatingSystemVersion := 1X; + OptionalHeader.MinorOperatingSystemVersion := 0X; + OptionalHeader.MajorImageVersion := 0X; + OptionalHeader.MinorImageVersion := 0X; + OptionalHeader.MajorSubsystemVersion := 4X; + OptionalHeader.MinorSubsystemVersion := 0X; + OptionalHeader.Win32VersionValue := 0H; + OptionalHeader.SizeOfImage := SectionAlignment; + OptionalHeader.SizeOfHeaders := 400H; + OptionalHeader.CheckSum := 0; + OptionalHeader.Subsystem := WCHR((2 + ORD(console)) * ORD(~dll)); + OptionalHeader.DllCharacteristics := 0040X; + OptionalHeader.SizeOfStackReserve := 100000H; + OptionalHeader.SizeOfStackCommit := 10000H; + OptionalHeader.SizeOfHeapReserve := 100000H; + OptionalHeader.SizeOfHeapCommit := 10000H; + OptionalHeader.LoaderFlags := 0; + OptionalHeader.NumberOfRvaAndSizes := IMAGE_NUMBEROF_DIRECTORY_ENTRIES; - InitSection(SectionHeaders[0], ".text", SHC_text); - SectionHeaders[0].VirtualSize := Size.Code; + FOR i := 0 TO IMAGE_NUMBEROF_DIRECTORY_ENTRIES - 1 DO + OptionalHeader.DataDirectory[i].VirtualAddress := 0; + OptionalHeader.DataDirectory[i].Size := 0 + END; + + InitSection(SectionHeaders[0], ".text", Size.Code, SHC_text); SectionHeaders[0].VirtualAddress := SectionAlignment; - SectionHeaders[0].SizeOfRawData := align(Size.Code, FileAlignment); - SectionHeaders[0].PointerToRawData := PEHeader.OptionalHeader.SizeOfHeaders; + SectionHeaders[0].PointerToRawData := OptionalHeader.SizeOfHeaders; - InitSection(SectionHeaders[1], ".data", SHC_data); - SectionHeaders[1].VirtualSize := Size.Data; - SectionHeaders[1].VirtualAddress := align(SectionHeaders[0].VirtualAddress + SectionHeaders[0].VirtualSize, SectionAlignment); - SectionHeaders[1].SizeOfRawData := align(Size.Data, FileAlignment); + InitSection(SectionHeaders[1], ".data", Size.Data, SHC_data); + SectionHeaders[1].VirtualAddress := WR.align(SectionHeaders[0].VirtualAddress + SectionHeaders[0].VirtualSize, SectionAlignment); SectionHeaders[1].PointerToRawData := SectionHeaders[0].PointerToRawData + SectionHeaders[0].SizeOfRawData; - InitSection(SectionHeaders[2], ".bss", SHC_bss); - SectionHeaders[2].VirtualSize := Size.Bss; - SectionHeaders[2].VirtualAddress := align(SectionHeaders[1].VirtualAddress + SectionHeaders[1].VirtualSize, SectionAlignment); - SectionHeaders[2].SizeOfRawData := 0; + InitSection(SectionHeaders[2], ".bss", Size.Bss, SHC_bss); + SectionHeaders[2].VirtualAddress := WR.align(SectionHeaders[1].VirtualAddress + SectionHeaders[1].VirtualSize, SectionAlignment); SectionHeaders[2].PointerToRawData := SectionHeaders[1].PointerToRawData + SectionHeaders[1].SizeOfRawData; + SectionHeaders[2].SizeOfRawData := 0; Size.Import := GetImportSize(program.imp_list); - InitSection(SectionHeaders[3], ".idata", SHC_data); - SectionHeaders[3].VirtualSize := Size.Import + CHL.Length(program.import); - SectionHeaders[3].VirtualAddress := align(SectionHeaders[2].VirtualAddress + SectionHeaders[2].VirtualSize, SectionAlignment); - SectionHeaders[3].SizeOfRawData := align(SectionHeaders[3].VirtualSize, FileAlignment); + InitSection(SectionHeaders[3], ".idata", Size.Import + CHL.Length(program._import), SHC_data); + SectionHeaders[3].VirtualAddress := WR.align(SectionHeaders[2].VirtualAddress + SectionHeaders[2].VirtualSize, SectionAlignment); SectionHeaders[3].PointerToRawData := SectionHeaders[2].PointerToRawData + SectionHeaders[2].SizeOfRawData; - Address.Code := SectionHeaders[0].VirtualAddress + PEHeader.OptionalHeader.ImageBase; - Address.Data := SectionHeaders[1].VirtualAddress + PEHeader.OptionalHeader.ImageBase; - Address.Bss := SectionHeaders[2].VirtualAddress + PEHeader.OptionalHeader.ImageBase; - Address.Import := SectionHeaders[3].VirtualAddress + PEHeader.OptionalHeader.ImageBase; + Address.Code := SectionHeaders[0].VirtualAddress + OptionalHeader.ImageBase; + Address.Data := SectionHeaders[1].VirtualAddress + OptionalHeader.ImageBase; + Address.Bss := SectionHeaders[2].VirtualAddress + OptionalHeader.ImageBase; + Address.Import := SectionHeaders[3].VirtualAddress + OptionalHeader.ImageBase; - fixup(program, Address); + fixup(program, Address, amd64); IF dll THEN - Size.Export := Export(program, SectionHeaders[1].VirtualAddress, ExportDir); + Size.Export := Export(program, SectionHeaders[1].VirtualAddress + program.modname, ExportDir); - InitSection(SectionHeaders[4], ".edata", SHC_data); - SectionHeaders[4].VirtualSize := Size.Export + CHL.Length(program.export); - SectionHeaders[4].VirtualAddress := align(SectionHeaders[3].VirtualAddress + SectionHeaders[3].VirtualSize, SectionAlignment); - SectionHeaders[4].SizeOfRawData := align(SectionHeaders[4].VirtualSize, FileAlignment); + InitSection(SectionHeaders[4], ".edata", Size.Export + CHL.Length(program.export), SHC_data); + SectionHeaders[4].VirtualAddress := WR.align(SectionHeaders[3].VirtualAddress + SectionHeaders[3].VirtualSize, SectionAlignment); SectionHeaders[4].PointerToRawData := SectionHeaders[3].PointerToRawData + SectionHeaders[3].SizeOfRawData; + + OptionalHeader.DataDirectory[0].VirtualAddress := SectionHeaders[4].VirtualAddress; + OptionalHeader.DataDirectory[0].Size := SectionHeaders[4].VirtualSize END; - FOR i := 0 TO IMAGE_NUMBEROF_DIRECTORY_ENTRIES - 1 DO - PEHeader.OptionalHeader.DataDirectory[i].VirtualAddress := 0; - PEHeader.OptionalHeader.DataDirectory[i].Size := 0 + OptionalHeader.DataDirectory[1].VirtualAddress := SectionHeaders[3].VirtualAddress; + OptionalHeader.DataDirectory[1].Size := SectionHeaders[3].VirtualSize; + + FOR i := 1 TO ORD(FileHeader.NumberOfSections) - 1 DO + INC(OptionalHeader.SizeOfInitializedData, SectionHeaders[i].SizeOfRawData) END; - IF dll THEN - PEHeader.OptionalHeader.DataDirectory[0].VirtualAddress := SectionHeaders[4].VirtualAddress; - PEHeader.OptionalHeader.DataDirectory[0].Size := SectionHeaders[4].VirtualSize - END; + OptionalHeader.SizeOfUninitializedData := WR.align(SectionHeaders[2].VirtualSize, FileAlignment); - PEHeader.OptionalHeader.DataDirectory[1].VirtualAddress := SectionHeaders[3].VirtualAddress; - PEHeader.OptionalHeader.DataDirectory[1].Size := SectionHeaders[3].VirtualSize; - - FOR i := 0 TO ORD(PEHeader.FileHeader.NumberOfSections) - 1 DO - INC(PEHeader.OptionalHeader.SizeOfInitializedData, SectionHeaders[i].SizeOfRawData) - END; - - DEC(PEHeader.OptionalHeader.SizeOfInitializedData, SectionHeaders[0].SizeOfRawData); - DEC(PEHeader.OptionalHeader.SizeOfInitializedData, SectionHeaders[2].SizeOfRawData); - - PEHeader.OptionalHeader.SizeOfUninitializedData := align(SectionHeaders[2].VirtualSize, FileAlignment); - - FOR i := 0 TO ORD(PEHeader.FileHeader.NumberOfSections) - 1 DO - INC(PEHeader.OptionalHeader.SizeOfImage, align(SectionHeaders[i].VirtualSize, SectionAlignment)) + FOR i := 0 TO ORD(FileHeader.NumberOfSections) - 1 DO + INC(OptionalHeader.SizeOfImage, WR.align(SectionHeaders[i].VirtualSize, SectionAlignment)) END; n := 0; @@ -634,23 +588,25 @@ BEGIN BIN.InitArray(msdos, n, "0E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F"); BIN.InitArray(msdos, n, "742062652072756E20696E20444F53206D6F64652E0D0A240000000000000000"); - File := WR.Create(FileName); + WR.Create(FileName); - WR.Write(File, msdos, LEN(msdos)); + WR.Write(msdos, LEN(msdos)); - WritePEHeader(File, PEHeader); + WR.Write(Signature, LEN(Signature)); + WriteFileHeader(FileHeader); + WriteOptHeader(OptionalHeader, amd64); - FOR i := 0 TO ORD(PEHeader.FileHeader.NumberOfSections) - 1 DO - WriteSectionHeader(File, SectionHeaders[i]) + FOR i := 0 TO ORD(FileHeader.NumberOfSections) - 1 DO + WriteSectionHeader(SectionHeaders[i]) END; - WR.Padding(File, FileAlignment); + WR.Padding(FileAlignment); - CHL.WriteToFile(File, program.code); - WR.Padding(File, FileAlignment); + CHL.WriteToFile(program.code); + WR.Padding(FileAlignment); - CHL.WriteToFile(File, program.data); - WR.Padding(File, FileAlignment); + CHL.WriteToFile(program.data); + WR.Padding(FileAlignment); n := (libcnt + 1) * 5; ImportTable := CHL.CreateIntList(); @@ -660,17 +616,17 @@ BEGIN END; i := 0; - import := program.imp_list.first(BIN.IMPRT); - WHILE import # NIL DO - IF import.label = 0 THEN - CHL.SetInt(ImportTable, i + 0, import.OriginalFirstThunk * SizeOfWord + SectionHeaders[3].VirtualAddress + n * SIZE_OF_DWORD); + _import := program.imp_list.first(BIN.IMPRT); + WHILE _import # NIL DO + IF _import.label = 0 THEN + CHL.SetInt(ImportTable, i + 0, _import.OriginalFirstThunk * SizeOfWord + SectionHeaders[3].VirtualAddress + n * SIZE_OF_DWORD); CHL.SetInt(ImportTable, i + 1, 0); CHL.SetInt(ImportTable, i + 2, 0); - CHL.SetInt(ImportTable, i + 3, import.nameoffs + Size.Import + SectionHeaders[3].VirtualAddress); - CHL.SetInt(ImportTable, i + 4, import.FirstThunk * SizeOfWord + SectionHeaders[3].VirtualAddress + n * SIZE_OF_DWORD); - i := i + 5 + CHL.SetInt(ImportTable, i + 3, _import.nameoffs + Size.Import + SectionHeaders[3].VirtualAddress); + CHL.SetInt(ImportTable, i + 4, _import.FirstThunk * SizeOfWord + SectionHeaders[3].VirtualAddress + n * SIZE_OF_DWORD); + INC(i, 5) END; - import := import.next(BIN.IMPRT) + _import := _import.next(BIN.IMPRT) END; CHL.SetInt(ImportTable, i + 0, 0); @@ -679,29 +635,30 @@ BEGIN CHL.SetInt(ImportTable, i + 3, 0); CHL.SetInt(ImportTable, i + 4, 0); - import := program.imp_list.first(BIN.IMPRT); - WHILE import # NIL DO - IF import.label # 0 THEN - CHL.SetInt(ImportTable, import.OriginalFirstThunk + n, import.nameoffs + Size.Import + SectionHeaders[3].VirtualAddress - 2); - CHL.SetInt(ImportTable, import.FirstThunk + n, import.nameoffs + Size.Import + SectionHeaders[3].VirtualAddress - 2) + _import := program.imp_list.first(BIN.IMPRT); + WHILE _import # NIL DO + IF _import.label # 0 THEN + temp := _import.nameoffs + Size.Import + SectionHeaders[3].VirtualAddress - 2; + CHL.SetInt(ImportTable, _import.OriginalFirstThunk + n, temp); + CHL.SetInt(ImportTable, _import.FirstThunk + n, temp) END; - import := import.next(BIN.IMPRT) + _import := _import.next(BIN.IMPRT) END; FOR i := 0 TO n - 1 DO - WR.Write32LE(File, CHL.GetInt(ImportTable, i)) + WR.Write32LE(CHL.GetInt(ImportTable, i)) END; FOR i := n TO CHL.Length(ImportTable) - 1 DO IF amd64 THEN - WR.Write64LE(File, CHL.GetInt(ImportTable, i)) + WR.Write64LE(CHL.GetInt(ImportTable, i)) ELSE - WR.Write32LE(File, CHL.GetInt(ImportTable, i)) + WR.Write32LE(CHL.GetInt(ImportTable, i)) END END; - CHL.WriteToFile(File, program.import); - WR.Padding(File, FileAlignment); + CHL.WriteToFile(program._import); + WR.Padding(FileAlignment); IF dll THEN @@ -709,29 +666,29 @@ BEGIN INC(ExportDir.AddressOfNames, SectionHeaders[4].VirtualAddress); INC(ExportDir.AddressOfNameOrdinals, SectionHeaders[4].VirtualAddress); - WriteExportDir(File, ExportDir); + WriteExportDir(ExportDir); export := program.exp_list.first(BIN.EXPRT); WHILE export # NIL DO - WR.Write32LE(File, export.label + SectionHeaders[0].VirtualAddress); + WR.Write32LE(export.label + SectionHeaders[0].VirtualAddress); export := export.next(BIN.EXPRT) END; export := program.exp_list.first(BIN.EXPRT); WHILE export # NIL DO - WR.Write32LE(File, export.nameoffs + Size.Export + SectionHeaders[4].VirtualAddress); + WR.Write32LE(export.nameoffs + Size.Export + SectionHeaders[4].VirtualAddress); export := export.next(BIN.EXPRT) END; FOR i := 0 TO ExportDir.NumberOfFunctions - 1 DO - WriteWord(File, WCHR(i)) + WriteWord(WCHR(i)) END; - CHL.WriteToFile(File, program.export); - WR.Padding(File, FileAlignment) + CHL.WriteToFile(program.export); + WR.Padding(FileAlignment) END; - WR.Close(File) + WR.Close END write; diff --git a/programs/develop/oberon07/Source/PROG.ob07 b/programs/develop/oberon07/Source/PROG.ob07 index a398bef3c..87cde889f 100644 --- a/programs/develop/oberon07/Source/PROG.ob07 +++ b/programs/develop/oberon07/Source/PROG.ob07 @@ -1,13 +1,13 @@ (* BSD 2-Clause License - Copyright (c) 2018-2019, Anton Krotov + Copyright (c) 2018-2020, Anton Krotov All rights reserved. *) MODULE PROG; -IMPORT SCAN, LISTS, ARITH, ERRORS, C := COLLECTIONS, IL, UTILS, TARGETS; +IMPORT SCAN, LISTS, ARITH, ERRORS, C := COLLECTIONS, IL, UTILS, TARGETS, STRINGS; CONST @@ -24,7 +24,7 @@ CONST tINTEGER* = 1; tBYTE* = 2; tCHAR* = 3; tSET* = 4; tBOOLEAN* = 5; tREAL* = 6; tARRAY* = 7; tRECORD* = 8; tPOINTER* = 9; tPROCEDURE* = 10; tSTRING* = 11; tNIL* = 12; - tCARD32* = 13; tANYREC* = 14; tWCHAR* = 15; + tCARD32* = 13; tANYREC* = 14; tWCHAR* = 15; tNONE* = 16; BASICTYPES* = {tINTEGER, tBYTE, tCHAR, tSET, tBOOLEAN, tREAL, tCARD32, tWCHAR}; @@ -35,20 +35,20 @@ CONST stPACK* = 17; stUNPK* = 18; sysADR* = 19; sysSIZE* = 20; sysGET* = 21; sysPUT* = 22; - stDISPOSE* = 23; stLSR* = 24; stBITS* = 25; sysCODE* = 26; - sysMOVE* = 27; stLENGTH* = 28; stMIN* = 29; stMAX* = 30; - sysSADR* = 31; sysTYPEID* = 32; sysCOPY* = 33; sysINF* = 34; - sysPUT8* = 35; sysPUT16* = 36; stCOPY* = 37; stWCHR* = 38; - sysWSADR* = 39; sysPUT32* = 40; (*sysNOP* = 41; sysEINT* = 42; - sysDINT* = 43;*) + stDISPOSE* = 23; stLSR* = 24; stBITS* = 25; sysCODE* = 26; + sysMOVE* = 27; stLENGTH* = 28; stMIN* = 29; stMAX* = 30; + sysSADR* = 31; sysTYPEID* = 32; sysCOPY* = 33; sysINF* = 34; + sysPUT8* = 35; sysPUT16* = 36; stCOPY* = 37; stWCHR* = 38; + sysWSADR* = 39; sysPUT32* = 40; (*sysNOP* = 41; sysEINT* = 42; + sysDINT* = 43;*)sysGET8* = 44; sysGET16* = 45; sysGET32* = 46; - default32* = 2; + default32* = 2; _default32* = default32 + 1; stdcall* = 4; _stdcall* = stdcall + 1; ccall* = 6; _ccall* = ccall + 1; ccall16* = 8; _ccall16* = ccall16 + 1; win64* = 10; _win64* = win64 + 1; stdcall64* = 12; _stdcall64* = stdcall64 + 1; - default64* = 14; + default64* = 14; _default64* = default64 + 1; systemv* = 16; _systemv* = systemv + 1; default16* = 18; code* = 20; _code* = code + 1; @@ -57,12 +57,12 @@ CONST callee_clean_up* = {default32, stdcall, _stdcall, default64, stdcall64, _stdcall64}; - sf_stdcall* = 0; sf_stdcall64* = 1; sf_ccall* = 2; sf_ccall16* = 3; - sf_win64* = 4; sf_systemv* = 5; sf_windows* = 6; sf_linux* = 7; - sf_code* = 8; - sf_noalign* = 9; + sf_stdcall* = 0; sf_stdcall64* = 1; sf_ccall* = 2; sf_ccall16* = 3; + sf_win64* = 4; sf_systemv* = 5; sf_windows* = 6; sf_linux* = 7; + sf_code* = 8; sf_oberon* = 9; + sf_noalign* = 10; - proc_flags* = {sf_stdcall, sf_stdcall64, sf_ccall, sf_ccall16, sf_win64, sf_systemv, sf_windows, sf_linux, sf_code}; + proc_flags* = {sf_stdcall, sf_stdcall64, sf_ccall, sf_ccall16, sf_win64, sf_systemv, sf_windows, sf_linux, sf_code, sf_oberon}; rec_flags* = {sf_noalign}; STACK_FRAME = 2; @@ -73,7 +73,7 @@ TYPE OPTIONS* = RECORD version*, stack*, ram*, rom*: INTEGER; - pic*: BOOLEAN; + pic*, lower*: BOOLEAN; checking*: SET END; @@ -82,13 +82,11 @@ TYPE UNIT* = POINTER TO rUNIT; - PROGRAM* = POINTER TO rPROGRAM; - - TYPE_* = POINTER TO rTYPE_; + _TYPE* = POINTER TO rTYPE; FRWPTR* = POINTER TO RECORD (LISTS.ITEM) - type: TYPE_; + _type: _TYPE; baseIdent: SCAN.IDENT; linked: BOOLEAN; @@ -102,7 +100,7 @@ TYPE label*: INTEGER; used*: BOOLEAN; processed*: BOOLEAN; - import*: LISTS.ITEM; + _import*: LISTS.ITEM; using*: LISTS.LIST; enter*, leave*: LISTS.ITEM @@ -117,7 +115,6 @@ TYPE rUNIT = RECORD (LISTS.ITEM) - program*: PROGRAM; name*: SCAN.IDENT; idents*: LISTS.LIST; frwPointers: LISTS.LIST; @@ -133,28 +130,28 @@ TYPE PARAM* = POINTER TO rPARAM; - rTYPE_ = RECORD (LISTS.ITEM) + rTYPE = RECORD (LISTS.ITEM) typ*: INTEGER; size*: INTEGER; parSize*: INTEGER; length*: INTEGER; align*: INTEGER; - base*: TYPE_; + base*: _TYPE; fields*: LISTS.LIST; params*: LISTS.LIST; unit*: UNIT; closed*: BOOLEAN; num*: INTEGER; call*: INTEGER; - import*: BOOLEAN; + _import*: BOOLEAN; noalign*: BOOLEAN END; rFIELD = RECORD (LISTS.ITEM) - type*: TYPE_; + _type*: _TYPE; name*: SCAN.IDENT; export*: BOOLEAN; offset*: INTEGER @@ -164,7 +161,7 @@ TYPE rPARAM = RECORD (LISTS.ITEM) name*: SCAN.IDENT; - type*: TYPE_; + _type*: _TYPE; vPar*: BOOLEAN; offset*: INTEGER @@ -175,10 +172,10 @@ TYPE name*: SCAN.IDENT; typ*: INTEGER; export*: BOOLEAN; - import*: LISTS.ITEM; + _import*: LISTS.ITEM; unit*: UNIT; value*: ARITH.VALUE; - type*: TYPE_; + _type*: _TYPE; stproc*: INTEGER; global*: BOOLEAN; scopeLvl*: INTEGER; @@ -188,7 +185,7 @@ TYPE END; - rPROGRAM = RECORD + PROGRAM = RECORD recCount: INTEGER; units*: LISTS.LIST; @@ -206,18 +203,20 @@ TYPE stTypes*: RECORD tINTEGER*, tBYTE*, tCHAR*, tWCHAR*, tSET*, tBOOLEAN*, tREAL*, - tSTRING*, tNIL*, tCARD32*, tANYREC*: TYPE_ + tSTRING*, tNIL*, tCARD32*, tANYREC*, tNONE*: _TYPE END END; - DELIMPORT = PROCEDURE (import: LISTS.ITEM); + DELIMPORT = PROCEDURE (_import: LISTS.ITEM); VAR + LowerCase: BOOLEAN; idents: C.COLLECTION; + program*: PROGRAM; PROCEDURE NewIdent (): IDENT; @@ -237,15 +236,15 @@ BEGIN END NewIdent; -PROCEDURE getOffset* (program: PROGRAM; varIdent: IDENT): INTEGER; +PROCEDURE getOffset* (varIdent: IDENT): INTEGER; VAR size: INTEGER; BEGIN IF varIdent.offset = -1 THEN - size := varIdent.type.size; + size := varIdent._type.size; IF varIdent.global THEN - IF UTILS.Align(program.bss, varIdent.type.align) THEN + IF UTILS.Align(program.bss, varIdent._type.align) THEN IF UTILS.maxint - program.bss >= size THEN varIdent.offset := program.bss; INC(program.bss, size) @@ -281,7 +280,7 @@ BEGIN IF (ident.typ = idVAR) & (ident.offset = -1) THEN ERRORS.HintMsg(ident.name.s, ident.pos.line, ident.pos.col, 0); IF ident.export THEN - offset := getOffset(unit.program, ident) + offset := getOffset(ident) END END; ident := ident.prev(IDENT) @@ -322,7 +321,6 @@ VAR item: IDENT; res: BOOLEAN; proc: PROC; - procs: LISTS.LIST; BEGIN ASSERT(unit # NIL); @@ -333,12 +331,12 @@ BEGIN IF res THEN item := NewIdent(); - item.name := ident; - item.typ := typ; - item.unit := NIL; - item.export := FALSE; - item.import := NIL; - item.type := NIL; + item.name := ident; + item.typ := typ; + item.unit := NIL; + item.export := FALSE; + item._import := NIL; + item._type := NIL; item.value.typ := 0; item.stproc := 0; @@ -348,13 +346,12 @@ BEGIN IF item.typ IN {idPROC, idIMP} THEN NEW(proc); - proc.import := NIL; + proc._import := NIL; proc.label := 0; proc.used := FALSE; proc.processed := FALSE; proc.using := LISTS.create(NIL); - procs := unit.program.procs; - LISTS.push(procs, proc); + LISTS.push(program.procs, proc); item.proc := proc END; @@ -393,16 +390,16 @@ BEGIN END UseProc; -PROCEDURE setVarsType* (unit: UNIT; type: TYPE_); +PROCEDURE setVarsType* (unit: UNIT; _type: _TYPE); VAR item: IDENT; BEGIN - ASSERT(type # NIL); + ASSERT(_type # NIL); item := unit.idents.last(IDENT); - WHILE (item # NIL) & (item.typ = idVAR) & (item.type = NIL) DO - item.type := type; + WHILE (item # NIL) & (item.typ = idVAR) & (item._type = NIL) DO + item._type := _type; item := item.prev(IDENT) END END setVarsType; @@ -481,10 +478,10 @@ BEGIN ERRORS.HintMsg(del.name.s, del.pos.line, del.pos.col, 0) END; IF (variables # NIL) & (del.typ IN {idVAR, idPARAM}) & (del.offset # -1) THEN - IF del.type.typ IN BASICTYPES - {tREAL} + {tPOINTER, tPROCEDURE} THEN + IF del._type.typ IN BASICTYPES - {tREAL} + {tPOINTER, tPROCEDURE} THEN lvar := IL.NewVar(); lvar.offset := del.offset; - lvar.size := del.type.size; + lvar.size := del._type.size; IF del.typ = idVAR THEN lvar.offset := -lvar.offset END; @@ -504,18 +501,18 @@ BEGIN END closeScope; -PROCEDURE frwPtr* (unit: UNIT; type: TYPE_; baseIdent: SCAN.IDENT; pos: SCAN.POSITION); +PROCEDURE frwPtr* (unit: UNIT; _type: _TYPE; baseIdent: SCAN.IDENT; pos: SCAN.POSITION); VAR newptr: FRWPTR; BEGIN ASSERT(unit # NIL); - ASSERT(type # NIL); + ASSERT(_type # NIL); ASSERT(baseIdent # NIL); NEW(newptr); - newptr.type := type; + newptr._type := _type; newptr.baseIdent := baseIdent; newptr.pos := pos; newptr.linked := FALSE; @@ -539,8 +536,8 @@ BEGIN ident := getIdent(unit, item.baseIdent, TRUE); IF (ident # NIL) THEN - IF (ident.typ = idTYPE) & (ident.type.typ = tRECORD) THEN - item.type.base := ident.type; + IF (ident.typ = idTYPE) & (ident._type.typ = tRECORD) THEN + item._type.base := ident._type; item.linked := TRUE ELSE item.notRecord := TRUE; @@ -558,7 +555,7 @@ BEGIN END linkPtr; -PROCEDURE isTypeEq* (t1, t2: TYPE_): BOOLEAN; +PROCEDURE isTypeEq* (t1, t2: _TYPE): BOOLEAN; VAR res: BOOLEAN; param1, param2: LISTS.ITEM; @@ -576,7 +573,7 @@ BEGIN res := ((t1.call = t2.call) OR (t1.call IN {code, _code}) OR (t2.call IN {code, _code})) & ((param1 # NIL) = (param2 # NIL)); WHILE res & (param1 # NIL) & (param2 # NIL) DO - res := (param1(PARAM).vPar = param2(PARAM).vPar) & isTypeEq(param1(PARAM).type, param2(PARAM).type); + res := (param1(PARAM).vPar = param2(PARAM).vPar) & isTypeEq(param1(PARAM)._type, param2(PARAM)._type); param1 := param1.next; param2 := param2.next; res := res & ((param1 # NIL) = (param2 # NIL)) @@ -594,7 +591,7 @@ BEGIN END isTypeEq; -PROCEDURE isBaseOf* (t0, t1: TYPE_): BOOLEAN; +PROCEDURE isBaseOf* (t0, t1: _TYPE): BOOLEAN; VAR res: BOOLEAN; @@ -617,19 +614,19 @@ BEGIN END isBaseOf; -PROCEDURE isOpenArray* (t: TYPE_): BOOLEAN; +PROCEDURE isOpenArray* (t: _TYPE): BOOLEAN; RETURN (t.typ = tARRAY) & (t.length = 0) END isOpenArray; -PROCEDURE arrcomp* (src, dst: TYPE_): BOOLEAN; +PROCEDURE arrcomp* (src, dst: _TYPE): BOOLEAN; RETURN (dst.typ = tARRAY) & isOpenArray(src) & ~isOpenArray(src.base) & ~isOpenArray(dst.base) & isTypeEq(src.base, dst.base) END arrcomp; -PROCEDURE getUnit* (program: PROGRAM; name: SCAN.IDENT): UNIT; +PROCEDURE getUnit* (name: SCAN.IDENT): UNIT; VAR item: UNIT; @@ -642,7 +639,7 @@ BEGIN item := item.next(UNIT) END; - IF (item = NIL) & (name.s = "SYSTEM") THEN + IF (item = NIL) & ((name.s = "SYSTEM") OR LowerCase & (name.s = "system")) THEN item := program.sysunit END @@ -650,36 +647,40 @@ BEGIN END getUnit; -PROCEDURE enterStTypes (unit: UNIT; program: PROGRAM); -VAR - ident: IDENT; +PROCEDURE enterStTypes (unit: UNIT); + + + PROCEDURE enter (unit: UNIT; name: SCAN.LEXSTR; _type: _TYPE); + VAR + ident: IDENT; + upper: SCAN.LEXSTR; + + BEGIN + IF LowerCase THEN + ident := addIdent(unit, SCAN.enterid(name), idTYPE); + ident._type := _type + END; + upper := name; + STRINGS.UpCase(upper); + ident := addIdent(unit, SCAN.enterid(upper), idTYPE); + ident._type := _type + END enter; + BEGIN - ident := addIdent(unit, SCAN.enterid("INTEGER"), idTYPE); - ident.type := program.stTypes.tINTEGER; - - ident := addIdent(unit, SCAN.enterid("BYTE"), idTYPE); - ident.type := program.stTypes.tBYTE; - - ident := addIdent(unit, SCAN.enterid("CHAR"), idTYPE); - ident.type := program.stTypes.tCHAR; - - ident := addIdent(unit, SCAN.enterid("SET"), idTYPE); - ident.type := program.stTypes.tSET; - - ident := addIdent(unit, SCAN.enterid("BOOLEAN"), idTYPE); - ident.type := program.stTypes.tBOOLEAN; + enter(unit, "integer", program.stTypes.tINTEGER); + enter(unit, "byte", program.stTypes.tBYTE); + enter(unit, "char", program.stTypes.tCHAR); + enter(unit, "set", program.stTypes.tSET); + enter(unit, "boolean", program.stTypes.tBOOLEAN); IF TARGETS.RealSize # 0 THEN - ident := addIdent(unit, SCAN.enterid("REAL"), idTYPE); - ident.type := program.stTypes.tREAL + enter(unit, "real", program.stTypes.tREAL) END; IF TARGETS.BitDepth >= 32 THEN - ident := addIdent(unit, SCAN.enterid("WCHAR"), idTYPE); - ident.type := program.stTypes.tWCHAR + enter(unit, "wchar", program.stTypes.tWCHAR) END - END enterStTypes; @@ -689,73 +690,91 @@ PROCEDURE enterStProcs (unit: UNIT); PROCEDURE EnterProc (unit: UNIT; name: SCAN.LEXSTR; proc: INTEGER); VAR ident: IDENT; + upper: SCAN.LEXSTR; + BEGIN - ident := addIdent(unit, SCAN.enterid(name), idSTPROC); - ident.stproc := proc + IF LowerCase THEN + ident := addIdent(unit, SCAN.enterid(name), idSTPROC); + ident.stproc := proc; + ident._type := program.stTypes.tNONE + END; + upper := name; + STRINGS.UpCase(upper); + ident := addIdent(unit, SCAN.enterid(upper), idSTPROC); + ident.stproc := proc; + ident._type := program.stTypes.tNONE END EnterProc; PROCEDURE EnterFunc (unit: UNIT; name: SCAN.LEXSTR; func: INTEGER); VAR ident: IDENT; + upper: SCAN.LEXSTR; + BEGIN - ident := addIdent(unit, SCAN.enterid(name), idSTFUNC); - ident.stproc := func + IF LowerCase THEN + ident := addIdent(unit, SCAN.enterid(name), idSTFUNC); + ident.stproc := func; + ident._type := program.stTypes.tNONE + END; + upper := name; + STRINGS.UpCase(upper); + ident := addIdent(unit, SCAN.enterid(upper), idSTFUNC); + ident.stproc := func; + ident._type := program.stTypes.tNONE END EnterFunc; BEGIN - EnterProc(unit, "ASSERT", stASSERT); - EnterProc(unit, "DEC", stDEC); - EnterProc(unit, "EXCL", stEXCL); - EnterProc(unit, "INC", stINC); - EnterProc(unit, "INCL", stINCL); - EnterProc(unit, "NEW", stNEW); - EnterProc(unit, "COPY", stCOPY); + EnterProc(unit, "assert", stASSERT); + EnterProc(unit, "dec", stDEC); + EnterProc(unit, "excl", stEXCL); + EnterProc(unit, "inc", stINC); + EnterProc(unit, "incl", stINCL); + EnterProc(unit, "new", stNEW); + EnterProc(unit, "copy", stCOPY); - EnterFunc(unit, "ABS", stABS); - EnterFunc(unit, "ASR", stASR); - EnterFunc(unit, "CHR", stCHR); - EnterFunc(unit, "LEN", stLEN); - EnterFunc(unit, "LSL", stLSL); - EnterFunc(unit, "ODD", stODD); - EnterFunc(unit, "ORD", stORD); - EnterFunc(unit, "ROR", stROR); - EnterFunc(unit, "BITS", stBITS); - EnterFunc(unit, "LSR", stLSR); - EnterFunc(unit, "LENGTH", stLENGTH); - EnterFunc(unit, "MIN", stMIN); - EnterFunc(unit, "MAX", stMAX); + EnterFunc(unit, "abs", stABS); + EnterFunc(unit, "asr", stASR); + EnterFunc(unit, "chr", stCHR); + EnterFunc(unit, "len", stLEN); + EnterFunc(unit, "lsl", stLSL); + EnterFunc(unit, "odd", stODD); + EnterFunc(unit, "ord", stORD); + EnterFunc(unit, "ror", stROR); + EnterFunc(unit, "bits", stBITS); + EnterFunc(unit, "lsr", stLSR); + EnterFunc(unit, "length", stLENGTH); + EnterFunc(unit, "min", stMIN); + EnterFunc(unit, "max", stMAX); IF TARGETS.RealSize # 0 THEN - EnterProc(unit, "PACK", stPACK); - EnterProc(unit, "UNPK", stUNPK); - EnterFunc(unit, "FLOOR", stFLOOR); - EnterFunc(unit, "FLT", stFLT) + EnterProc(unit, "pack", stPACK); + EnterProc(unit, "unpk", stUNPK); + EnterFunc(unit, "floor", stFLOOR); + EnterFunc(unit, "flt", stFLT) END; IF TARGETS.BitDepth >= 32 THEN - EnterFunc(unit, "WCHR", stWCHR) + EnterFunc(unit, "wchr", stWCHR) END; IF TARGETS.Dispose THEN - EnterProc(unit, "DISPOSE", stDISPOSE) + EnterProc(unit, "dispose", stDISPOSE) END END enterStProcs; -PROCEDURE newUnit* (program: PROGRAM; name: SCAN.IDENT): UNIT; +PROCEDURE newUnit* (name: SCAN.IDENT): UNIT; VAR unit: UNIT; BEGIN - ASSERT(program # NIL); ASSERT(name # NIL); NEW(unit); - unit.program := program; unit.name := name; unit.closed := FALSE; unit.idents := LISTS.create(NIL); @@ -763,7 +782,7 @@ BEGIN ASSERT(openScope(unit, NIL)); - enterStTypes(unit, program); + enterStTypes(unit); enterStProcs(unit); ASSERT(openScope(unit, NIL)); @@ -785,7 +804,7 @@ BEGIN END newUnit; -PROCEDURE getField* (self: TYPE_; name: SCAN.IDENT; unit: UNIT): FIELD; +PROCEDURE getField* (self: _TYPE; name: SCAN.IDENT; unit: UNIT): FIELD; VAR field: FIELD; @@ -817,7 +836,7 @@ BEGIN END getField; -PROCEDURE addField* (self: TYPE_; name: SCAN.IDENT; export: BOOLEAN): BOOLEAN; +PROCEDURE addField* (self: _TYPE; name: SCAN.IDENT; export: BOOLEAN): BOOLEAN; VAR field: FIELD; res: BOOLEAN; @@ -832,7 +851,7 @@ BEGIN field.name := name; field.export := export; - field.type := NIL; + field._type := NIL; field.offset := self.size; LISTS.push(self.fields, field) @@ -842,33 +861,33 @@ BEGIN END addField; -PROCEDURE setFields* (self: TYPE_; type: TYPE_): BOOLEAN; +PROCEDURE setFields* (self: _TYPE; _type: _TYPE): BOOLEAN; VAR item: FIELD; res: BOOLEAN; BEGIN - ASSERT(type # NIL); + ASSERT(_type # NIL); item := self.fields.first(FIELD); - WHILE (item # NIL) & (item.type # NIL) DO + WHILE (item # NIL) & (item._type # NIL) DO item := item.next(FIELD) END; res := TRUE; - WHILE res & (item # NIL) & (item.type = NIL) DO - item.type := type; + WHILE res & (item # NIL) & (item._type = NIL) DO + item._type := _type; IF ~self.noalign THEN - res := UTILS.Align(self.size, type.align) + res := UTILS.Align(self.size, _type.align) ELSE res := TRUE END; item.offset := self.size; - res := res & (UTILS.maxint - self.size >= type.size); + res := res & (UTILS.maxint - self.size >= _type.size); IF res THEN - INC(self.size, type.size) + INC(self.size, _type.size) END; item := item.next(FIELD) END @@ -877,7 +896,7 @@ BEGIN END setFields; -PROCEDURE getParam* (self: TYPE_; name: SCAN.IDENT): PARAM; +PROCEDURE getParam* (self: _TYPE; name: SCAN.IDENT): PARAM; VAR item: PARAM; @@ -894,7 +913,7 @@ BEGIN END getParam; -PROCEDURE addParam* (self: TYPE_; name: SCAN.IDENT; vPar: BOOLEAN): BOOLEAN; +PROCEDURE addParam* (self: _TYPE; name: SCAN.IDENT; vPar: BOOLEAN): BOOLEAN; VAR param: PARAM; res: BOOLEAN; @@ -907,9 +926,9 @@ BEGIN IF res THEN NEW(param); - param.name := name; - param.type := NIL; - param.vPar := vPar; + param.name := name; + param._type := NIL; + param.vPar := vPar; LISTS.push(self.params, param) END @@ -918,7 +937,7 @@ BEGIN END addParam; -PROCEDURE Dim* (t: TYPE_): INTEGER; +PROCEDURE Dim* (t: _TYPE): INTEGER; VAR res: INTEGER; @@ -932,14 +951,14 @@ BEGIN END Dim; -PROCEDURE OpenBase* (t: TYPE_): TYPE_; +PROCEDURE OpenBase* (t: _TYPE): _TYPE; BEGIN WHILE isOpenArray(t) DO t := t.base END RETURN t END OpenBase; -PROCEDURE getFloatParamsPos* (self: TYPE_; maxoffs: INTEGER; VAR int, flt: INTEGER): SET; +PROCEDURE getFloatParamsPos* (self: _TYPE; maxoffs: INTEGER; VAR int, flt: INTEGER): SET; VAR res: SET; param: PARAM; @@ -950,7 +969,7 @@ BEGIN flt := 0; param := self.params.first(PARAM); WHILE (param # NIL) & (param.offset <= maxoffs + STACK_FRAME) DO - IF ~param.vPar & (param.type.typ = tREAL) THEN + IF ~param.vPar & (param._type.typ = tREAL) THEN INCL(res, param.offset - STACK_FRAME); INC(flt) END; @@ -963,49 +982,49 @@ BEGIN END getFloatParamsPos; -PROCEDURE setParams* (self: TYPE_; type: TYPE_); +PROCEDURE setParams* (self: _TYPE; _type: _TYPE); VAR item: LISTS.ITEM; param: PARAM; word, size: INTEGER; BEGIN - ASSERT(type # NIL); + ASSERT(_type # NIL); word := UTILS.target.bit_depth DIV 8; item := self.params.first; - WHILE (item # NIL) & (item(PARAM).type # NIL) DO + WHILE (item # NIL) & (item(PARAM)._type # NIL) DO item := item.next END; - WHILE (item # NIL) & (item(PARAM).type = NIL) DO + WHILE (item # NIL) & (item(PARAM)._type = NIL) DO param := item(PARAM); - param.type := type; + param._type := _type; IF param.vPar THEN - IF type.typ = tRECORD THEN + IF _type.typ = tRECORD THEN size := 2 - ELSIF isOpenArray(type) THEN - size := Dim(type) + 1 + ELSIF isOpenArray(_type) THEN + size := Dim(_type) + 1 ELSE size := 1 END; - param.offset := self.parSize + ORD(type.typ = tRECORD) + Dim(type) + STACK_FRAME; + param.offset := self.parSize + ORD(_type.typ = tRECORD) + Dim(_type) + STACK_FRAME; INC(self.parSize, size) ELSE - IF type.typ IN {tRECORD, tARRAY} THEN - IF isOpenArray(type) THEN - size := Dim(type) + 1 + IF _type.typ IN {tRECORD, tARRAY} THEN + IF isOpenArray(_type) THEN + size := Dim(_type) + 1 ELSE size := 1 END ELSE - size := type.size; + size := _type.size; ASSERT(UTILS.Align(size, word)); size := size DIV word END; - param.offset := self.parSize + Dim(type) + STACK_FRAME; + param.offset := self.parSize + Dim(_type) + STACK_FRAME; INC(self.parSize, size) END; @@ -1015,9 +1034,9 @@ BEGIN END setParams; -PROCEDURE enterType* (program: PROGRAM; typ, size, length: INTEGER; unit: UNIT): TYPE_; +PROCEDURE enterType* (typ, size, length: INTEGER; unit: UNIT): _TYPE; VAR - t: TYPE_; + t: _TYPE; BEGIN NEW(t); @@ -1038,7 +1057,7 @@ BEGIN |64: t.call := default64 END; - t.import := FALSE; + t._import := FALSE; t.noalign := FALSE; t.parSize := 0; @@ -1058,9 +1077,9 @@ BEGIN END enterType; -PROCEDURE getType* (program: PROGRAM; typ: INTEGER): TYPE_; +PROCEDURE getType* (typ: INTEGER): _TYPE; VAR - res: TYPE_; + res: _TYPE; BEGIN @@ -1078,7 +1097,7 @@ BEGIN END getType; -PROCEDURE createSysUnit (program: PROGRAM); +PROCEDURE createSysUnit; VAR ident: IDENT; unit: UNIT; @@ -1087,49 +1106,68 @@ VAR PROCEDURE EnterProc (sys: UNIT; name: SCAN.LEXSTR; idtyp, proc: INTEGER); VAR ident: IDENT; + upper: SCAN.LEXSTR; + BEGIN - ident := addIdent(sys, SCAN.enterid(name), idtyp); + IF LowerCase THEN + ident := addIdent(sys, SCAN.enterid(name), idtyp); + ident.stproc := proc; + ident._type := program.stTypes.tNONE; + ident.export := TRUE + END; + upper := name; + STRINGS.UpCase(upper); + ident := addIdent(sys, SCAN.enterid(upper), idtyp); ident.stproc := proc; + ident._type := program.stTypes.tNONE; ident.export := TRUE END EnterProc; BEGIN - unit := newUnit(program, SCAN.enterid("$SYSTEM")); + unit := newUnit(SCAN.enterid("$SYSTEM")); - EnterProc(unit, "ADR", idSYSFUNC, sysADR); - EnterProc(unit, "SIZE", idSYSFUNC, sysSIZE); - EnterProc(unit, "SADR", idSYSFUNC, sysSADR); - EnterProc(unit, "TYPEID", idSYSFUNC, sysTYPEID); + EnterProc(unit, "adr", idSYSFUNC, sysADR); + EnterProc(unit, "size", idSYSFUNC, sysSIZE); + EnterProc(unit, "sadr", idSYSFUNC, sysSADR); + EnterProc(unit, "typeid", idSYSFUNC, sysTYPEID); - EnterProc(unit, "GET", idSYSPROC, sysGET); - EnterProc(unit, "PUT8", idSYSPROC, sysPUT8); - EnterProc(unit, "PUT", idSYSPROC, sysPUT); - EnterProc(unit, "CODE", idSYSPROC, sysCODE); - EnterProc(unit, "MOVE", idSYSPROC, sysMOVE); + EnterProc(unit, "get", idSYSPROC, sysGET); + EnterProc(unit, "get8", idSYSPROC, sysGET8); + EnterProc(unit, "put", idSYSPROC, sysPUT); + EnterProc(unit, "put8", idSYSPROC, sysPUT8); + EnterProc(unit, "code", idSYSPROC, sysCODE); + EnterProc(unit, "move", idSYSPROC, sysMOVE); (* IF program.target.sys = mConst.Target_iMSP430 THEN - EnterProc(unit, "NOP", idSYSPROC, sysNOP); - EnterProc(unit, "EINT", idSYSPROC, sysEINT); - EnterProc(unit, "DINT", idSYSPROC, sysDINT) + EnterProc(unit, "nop", idSYSPROC, sysNOP); + EnterProc(unit, "eint", idSYSPROC, sysEINT); + EnterProc(unit, "dint", idSYSPROC, sysDINT) END; *) IF TARGETS.RealSize # 0 THEN - EnterProc(unit, "INF", idSYSFUNC, sysINF); + EnterProc(unit, "inf", idSYSFUNC, sysINF); END; IF TARGETS.CPU IN {TARGETS.cpuX86, TARGETS.cpuAMD64} THEN - EnterProc(unit, "COPY", idSYSPROC, sysCOPY) + EnterProc(unit, "copy", idSYSPROC, sysCOPY) END; IF TARGETS.BitDepth >= 32 THEN - EnterProc(unit, "WSADR", idSYSFUNC, sysWSADR); - EnterProc(unit, "PUT32", idSYSPROC, sysPUT32); - EnterProc(unit, "PUT16", idSYSPROC, sysPUT16); + EnterProc(unit, "wsadr", idSYSFUNC, sysWSADR); + EnterProc(unit, "put16", idSYSPROC, sysPUT16); + EnterProc(unit, "put32", idSYSPROC, sysPUT32); + EnterProc(unit, "get16", idSYSPROC, sysGET16); + EnterProc(unit, "get32", idSYSPROC, sysGET32); + IF LowerCase THEN + ident := addIdent(unit, SCAN.enterid("card32"), idTYPE); + ident._type := program.stTypes.tCARD32; + ident.export := TRUE + END; ident := addIdent(unit, SCAN.enterid("CARD32"), idTYPE); - ident.type := program.stTypes.tCARD32; - ident.export := TRUE + ident._type := program.stTypes.tCARD32; + ident.export := TRUE; END; closeUnit(unit); @@ -1138,7 +1176,7 @@ BEGIN END createSysUnit; -PROCEDURE DelUnused* (program: PROGRAM; DelImport: DELIMPORT); +PROCEDURE DelUnused* (DelImport: DELIMPORT); VAR proc: PROC; flag: BOOLEAN; @@ -1180,10 +1218,10 @@ BEGIN WHILE proc # NIL DO IF ~proc.used THEN - IF proc.import = NIL THEN + IF proc._import = NIL THEN IL.delete2(proc.enter, proc.leave) ELSE - DelImport(proc.import) + DelImport(proc._import) END END; proc := proc.next(PROC) @@ -1192,24 +1230,28 @@ BEGIN END DelUnused; -PROCEDURE create* (options: OPTIONS): PROGRAM; -VAR - program: PROGRAM; - +PROCEDURE ResetLocSize*; BEGIN + program.locsize := 0 +END ResetLocSize; + + +PROCEDURE create* (options: OPTIONS); +BEGIN + LowerCase := options.lower; + SCAN.init(options.lower); idents := C.create(); UTILS.SetBitDepth(TARGETS.BitDepth, TARGETS.RealSize = 8); - NEW(program); program.options := options; CASE TARGETS.OS OF - |TARGETS.osWIN32: program.sysflags := {sf_windows, sf_stdcall, sf_ccall, sf_ccall16, sf_noalign} - |TARGETS.osLINUX32: program.sysflags := {sf_linux, sf_stdcall, sf_ccall, sf_ccall16, sf_noalign} - |TARGETS.osKOS: program.sysflags := {sf_stdcall, sf_ccall, sf_ccall16, sf_noalign} - |TARGETS.osWIN64: program.sysflags := {sf_windows, sf_stdcall64, sf_win64, sf_systemv, sf_noalign} - |TARGETS.osLINUX64: program.sysflags := {sf_linux, sf_stdcall64, sf_win64, sf_systemv, sf_noalign} + |TARGETS.osWIN32: program.sysflags := {sf_oberon, sf_windows, sf_stdcall, sf_ccall, sf_ccall16, sf_noalign} + |TARGETS.osLINUX32: program.sysflags := {sf_oberon, sf_linux, sf_stdcall, sf_ccall, sf_ccall16, sf_noalign} + |TARGETS.osKOS: program.sysflags := {sf_oberon, sf_stdcall, sf_ccall, sf_ccall16, sf_noalign} + |TARGETS.osWIN64: program.sysflags := {sf_oberon, sf_windows, sf_stdcall64, sf_win64, sf_systemv, sf_noalign} + |TARGETS.osLINUX64: program.sysflags := {sf_oberon, sf_linux, sf_stdcall64, sf_win64, sf_systemv, sf_noalign} |TARGETS.osNONE: program.sysflags := {sf_code} END; @@ -1220,11 +1262,11 @@ BEGIN program.types := LISTS.create(NIL); program.procs := LISTS.create(NIL); - program.stTypes.tINTEGER := enterType(program, tINTEGER, TARGETS.WordSize, 0, NIL); - program.stTypes.tBYTE := enterType(program, tBYTE, 1, 0, NIL); - program.stTypes.tCHAR := enterType(program, tCHAR, 1, 0, NIL); - program.stTypes.tSET := enterType(program, tSET, TARGETS.WordSize, 0, NIL); - program.stTypes.tBOOLEAN := enterType(program, tBOOLEAN, 1, 0, NIL); + program.stTypes.tINTEGER := enterType(tINTEGER, TARGETS.WordSize, 0, NIL); + program.stTypes.tBYTE := enterType(tBYTE, 1, 0, NIL); + program.stTypes.tCHAR := enterType(tCHAR, 1, 0, NIL); + program.stTypes.tSET := enterType(tSET, TARGETS.WordSize, 0, NIL); + program.stTypes.tBOOLEAN := enterType(tBOOLEAN, 1, 0, NIL); program.stTypes.tINTEGER.align := TARGETS.WordSize; program.stTypes.tBYTE.align := 1; @@ -1233,26 +1275,24 @@ BEGIN program.stTypes.tBOOLEAN.align := 1; IF TARGETS.BitDepth >= 32 THEN - program.stTypes.tWCHAR := enterType(program, tWCHAR, 2, 0, NIL); - program.stTypes.tCARD32 := enterType(program, tCARD32, 4, 0, NIL); + program.stTypes.tWCHAR := enterType(tWCHAR, 2, 0, NIL); + program.stTypes.tCARD32 := enterType(tCARD32, 4, 0, NIL); program.stTypes.tWCHAR.align := 2; program.stTypes.tCARD32.align := 4 END; IF TARGETS.RealSize # 0 THEN - program.stTypes.tREAL := enterType(program, tREAL, TARGETS.RealSize, 0, NIL); + program.stTypes.tREAL := enterType(tREAL, TARGETS.RealSize, 0, NIL); program.stTypes.tREAL.align := TARGETS.RealSize END; - program.stTypes.tSTRING := enterType(program, tSTRING, TARGETS.WordSize, 0, NIL); - program.stTypes.tNIL := enterType(program, tNIL, TARGETS.WordSize, 0, NIL); - - program.stTypes.tANYREC := enterType(program, tRECORD, 0, 0, NIL); + program.stTypes.tSTRING := enterType(tSTRING, TARGETS.WordSize, 0, NIL); + program.stTypes.tNIL := enterType(tNIL, TARGETS.WordSize, 0, NIL); + program.stTypes.tNONE := enterType(tNONE, 0, 0, NIL); + program.stTypes.tANYREC := enterType(tRECORD, 0, 0, NIL); program.stTypes.tANYREC.closed := TRUE; - createSysUnit(program) - - RETURN program + createSysUnit END create; diff --git a/programs/develop/oberon07/Source/REG.ob07 b/programs/develop/oberon07/Source/REG.ob07 index f0543cace..32dbbf60d 100644 --- a/programs/develop/oberon07/Source/REG.ob07 +++ b/programs/develop/oberon07/Source/REG.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018-2019, Anton Krotov + Copyright (c) 2018-2020, Anton Krotov All rights reserved. *) @@ -156,8 +156,8 @@ END GetAnyReg; PROCEDURE GetReg* (VAR R: REGS; reg: INTEGER): BOOLEAN; VAR - free, n: INTEGER; - res: BOOLEAN; + free: INTEGER; + res: BOOLEAN; PROCEDURE exch (VAR R: REGS; reg1, reg2: INTEGER); @@ -178,8 +178,8 @@ BEGIN Put(R, reg); res := TRUE ELSE - n := InStk(R, reg); - IF n # -1 THEN + res := InStk(R, reg) # -1; + IF res THEN free := GetFreeReg(R); IF free # -1 THEN Put(R, free); @@ -192,10 +192,7 @@ BEGIN IF free # reg THEN exch(R, reg, free) END - END; - res := TRUE - ELSE - res := FALSE + END END END diff --git a/programs/develop/oberon07/Source/RVM32I.ob07 b/programs/develop/oberon07/Source/RVM32I.ob07 new file mode 100644 index 000000000..0ac9fefe3 --- /dev/null +++ b/programs/develop/oberon07/Source/RVM32I.ob07 @@ -0,0 +1,1302 @@ +(* + BSD 2-Clause License + + Copyright (c) 2020, Anton Krotov + All rights reserved. +*) + +MODULE RVM32I; + +IMPORT + + PROG, WR := WRITER, IL, CHL := CHUNKLISTS, REG, UTILS, STRINGS, ERRORS; + + +CONST + + LTypes = 0; + LStrings = 1; + LGlobal = 2; + LHeap = 3; + LStack = 4; + + numGPRs = 3; + + R0 = 0; R1 = 1; + BP = 3; SP = 4; + + ACC = R0; + + GPRs = {0 .. 2} + {5 .. numGPRs + 1}; + + opSTOP = 0; opRET = 1; opENTER = 2; opNEG = 3; opNOT = 4; opABS = 5; + opXCHG = 6; opLDR8 = 7; opLDR16 = 8; opLDR32 = 9; opPUSH = 10; opPUSHC = 11; + opPOP = 12; opJGZ = 13; opJZ = 14; opJNZ = 15; opLLA = 16; opJGA = 17; + opJLA = 18; opJMP = 19; opCALL = 20; opCALLI = 21; + + opMOV = 22; opMUL = 24; opADD = 26; opSUB = 28; opDIV = 30; opMOD = 32; + opSTR8 = 34; opSTR16 = 36; opSTR32 = 38; opINCL = 40; opEXCL = 42; + opIN = 44; opAND = 46; opOR = 48; opXOR = 50; opASR = 52; opLSR = 54; + opLSL = 56; opROR = 58; opMIN = 60; opMAX = 62; opEQ = 64; opNE = 66; + opLT = 68; opLE = 70; opGT = 72; opGE = 74; opBT = 76; + + opMOVC = 23; opMULC = 25; opADDC = 27; opSUBC = 29; opDIVC = 31; opMODC = 33; + opSTR8C = 35; opSTR16C = 37; opSTR32C = 39; opINCLC = 41; opEXCLC = 43; + opINC = 45; opANDC = 47; opORC = 49; opXORC = 51; opASRC = 53; opLSRC = 55; + opLSLC = 57; opRORC = 59; opMINC = 61; opMAXC = 63; opEQC = 65; opNEC = 67; + opLTC = 69; opLEC = 71; opGTC = 73; opGEC = 75; opBTC = 77; + + opLEA = 78; opLABEL = 79; + + inf = 7F800000H; + + +VAR + + R: REG.REGS; count: INTEGER; + + +PROCEDURE OutByte (n: BYTE); +BEGIN + WR.WriteByte(n); + INC(count) +END OutByte; + + +PROCEDURE OutInt (n: INTEGER); +BEGIN + WR.Write32LE(n); + INC(count, 4) +END OutInt; + + +PROCEDURE Emit (op, par1, par2: INTEGER); +BEGIN + OutInt(op); + OutInt(par1); + OutInt(par2) +END Emit; + + +PROCEDURE drop; +BEGIN + REG.Drop(R) +END drop; + + +PROCEDURE GetAnyReg (): INTEGER; + RETURN REG.GetAnyReg(R) +END GetAnyReg; + + +PROCEDURE GetAcc; +BEGIN + ASSERT(REG.GetReg(R, ACC)) +END GetAcc; + + +PROCEDURE UnOp (VAR r: INTEGER); +BEGIN + REG.UnOp(R, r) +END UnOp; + + +PROCEDURE BinOp (VAR r1, r2: INTEGER); +BEGIN + REG.BinOp(R, r1, r2) +END BinOp; + + +PROCEDURE PushAll (NumberOfParameters: INTEGER); +BEGIN + REG.PushAll(R); + DEC(R.pushed, NumberOfParameters) +END PushAll; + + +PROCEDURE push (r: INTEGER); +BEGIN + Emit(opPUSH, r, 0) +END push; + + +PROCEDURE pop (r: INTEGER); +BEGIN + Emit(opPOP, r, 0) +END pop; + + +PROCEDURE mov (r1, r2: INTEGER); +BEGIN + Emit(opMOV, r1, r2) +END mov; + + +PROCEDURE xchg (r1, r2: INTEGER); +BEGIN + Emit(opXCHG, r1, r2) +END xchg; + + +PROCEDURE addrc (r, c: INTEGER); +BEGIN + Emit(opADDC, r, c) +END addrc; + + +PROCEDURE subrc (r, c: INTEGER); +BEGIN + Emit(opSUBC, r, c) +END subrc; + + +PROCEDURE movrc (r, c: INTEGER); +BEGIN + Emit(opMOVC, r, c) +END movrc; + + +PROCEDURE pushc (c: INTEGER); +BEGIN + Emit(opPUSHC, c, 0) +END pushc; + + +PROCEDURE add (r1, r2: INTEGER); +BEGIN + Emit(opADD, r1, r2) +END add; + + +PROCEDURE sub (r1, r2: INTEGER); +BEGIN + Emit(opSUB, r1, r2) +END sub; + + +PROCEDURE ldr32 (r1, r2: INTEGER); +BEGIN + Emit(opLDR32, r1, r2) +END ldr32; + + +PROCEDURE ldr16 (r1, r2: INTEGER); +BEGIN + Emit(opLDR16, r1, r2) +END ldr16; + + +PROCEDURE ldr8 (r1, r2: INTEGER); +BEGIN + Emit(opLDR8, r1, r2) +END ldr8; + + +PROCEDURE str32 (r1, r2: INTEGER); +BEGIN + Emit(opSTR32, r1, r2) +END str32; + + +PROCEDURE str16 (r1, r2: INTEGER); +BEGIN + Emit(opSTR16, r1, r2) +END str16; + + +PROCEDURE str8 (r1, r2: INTEGER); +BEGIN + Emit(opSTR8, r1, r2) +END str8; + + +PROCEDURE GlobalAdr (r, offset: INTEGER); +BEGIN + Emit(opLEA, r + 256 * LGlobal, offset) +END GlobalAdr; + + +PROCEDURE StrAdr (r, offset: INTEGER); +BEGIN + Emit(opLEA, r + 256 * LStrings, offset) +END StrAdr; + + +PROCEDURE ProcAdr (r, label: INTEGER); +BEGIN + Emit(opLLA, r, label) +END ProcAdr; + + +PROCEDURE jnz (r, label: INTEGER); +BEGIN + Emit(opJNZ, r, label) +END jnz; + + +PROCEDURE CallRTL (proc, par: INTEGER); +BEGIN + Emit(opCALL, IL.codes.rtl[proc], 0); + addrc(SP, par * 4) +END CallRTL; + + +PROCEDURE translate; +VAR + cmd: IL.COMMAND; + opcode, param1, param2: INTEGER; + r1, r2, r3: INTEGER; + +BEGIN + cmd := IL.codes.commands.first(IL.COMMAND); + + WHILE cmd # NIL DO + + param1 := cmd.param1; + param2 := cmd.param2; + opcode := cmd.opcode; + + CASE opcode OF + + |IL.opJMP: + Emit(opJMP, param1, 0) + + |IL.opLABEL: + Emit(opLABEL, param1, 0) + + |IL.opCALL: + Emit(opCALL, param1, 0) + + |IL.opCALLP: + UnOp(r1); + Emit(opCALLI, r1, 0); + drop; + ASSERT(R.top = -1) + + |IL.opPUSHC: + pushc(param2) + + |IL.opCLEANUP: + IF param2 # 0 THEN + addrc(SP, param2 * 4) + END + + |IL.opNOP, IL.opAND, IL.opOR: + + |IL.opSADR: + StrAdr(GetAnyReg(), param2) + + |IL.opGADR: + GlobalAdr(GetAnyReg(), param2) + + |IL.opLADR: + r1 := GetAnyReg(); + mov(r1, BP); + addrc(r1, param2 * 4) + + |IL.opPARAM: + IF param2 = 1 THEN + UnOp(r1); + push(r1); + drop + ELSE + ASSERT(R.top + 1 <= param2); + PushAll(param2) + END + + |IL.opONERR: + pushc(param2); + Emit(opJMP, param1, 0) + + |IL.opPRECALL: + PushAll(0) + + |IL.opRES, IL.opRESF: + ASSERT(R.top = -1); + GetAcc + + |IL.opENTER: + ASSERT(R.top = -1); + Emit(opLABEL, param1, 0); + Emit(opENTER, param2, 0) + + |IL.opLEAVE, IL.opLEAVER, IL.opLEAVEF: + IF opcode # IL.opLEAVE THEN + UnOp(r1); + IF r1 # ACC THEN + GetAcc; + ASSERT(REG.Exchange(R, r1, ACC)); + drop + END; + drop + END; + + ASSERT(R.top = -1); + + IF param1 > 0 THEN + mov(SP, BP) + END; + + pop(BP); + + Emit(opRET, 0, 0) + + |IL.opLEAVEC: + Emit(opRET, 0, 0) + + |IL.opCONST: + movrc(GetAnyReg(), param2) + + |IL.opDROP: + UnOp(r1); + drop + + |IL.opSAVEC: + UnOp(r1); + Emit(opSTR32C, r1, param2); + drop + + |IL.opSAVE8C: + UnOp(r1); + Emit(opSTR8C, r1, param2 MOD 256); + drop + + |IL.opSAVE16C: + UnOp(r1); + Emit(opSTR16C, r1, param2 MOD 65536); + drop + + |IL.opSAVE, IL.opSAVE32, IL.opSAVEF: + BinOp(r2, r1); + str32(r1, r2); + drop; + drop + + |IL.opSAVEFI: + BinOp(r2, r1); + str32(r2, r1); + drop; + drop + + |IL.opSAVE8: + BinOp(r2, r1); + str8(r1, r2); + drop; + drop + + |IL.opSAVE16: + BinOp(r2, r1); + str16(r1, r2); + drop; + drop + + |IL.opGLOAD32: + r1 := GetAnyReg(); + GlobalAdr(r1, param2); + ldr32(r1, r1) + + |IL.opVADR, IL.opLLOAD32: + r1 := GetAnyReg(); + mov(r1, BP); + addrc(r1, param2 * 4); + ldr32(r1, r1) + + |IL.opVLOAD32: + r1 := GetAnyReg(); + mov(r1, BP); + addrc(r1, param2 * 4); + ldr32(r1, r1); + ldr32(r1, r1) + + |IL.opGLOAD16: + r1 := GetAnyReg(); + GlobalAdr(r1, param2); + ldr16(r1, r1) + + |IL.opLLOAD16: + r1 := GetAnyReg(); + mov(r1, BP); + addrc(r1, param2 * 4); + ldr16(r1, r1) + + |IL.opVLOAD16: + r1 := GetAnyReg(); + mov(r1, BP); + addrc(r1, param2 * 4); + ldr32(r1, r1); + ldr16(r1, r1) + + |IL.opGLOAD8: + r1 := GetAnyReg(); + GlobalAdr(r1, param2); + ldr8(r1, r1) + + |IL.opLLOAD8: + r1 := GetAnyReg(); + mov(r1, BP); + addrc(r1, param2 * 4); + ldr8(r1, r1) + + |IL.opVLOAD8: + r1 := GetAnyReg(); + mov(r1, BP); + addrc(r1, param2 * 4); + ldr32(r1, r1); + ldr8(r1, r1) + + |IL.opLOAD8: + UnOp(r1); + ldr8(r1, r1) + + |IL.opLOAD16: + UnOp(r1); + ldr16(r1, r1) + + |IL.opLOAD32, IL.opLOADF: + UnOp(r1); + ldr32(r1, r1) + + |IL.opLOOP, IL.opENDLOOP: + + |IL.opUMINUS: + UnOp(r1); + Emit(opNEG, r1, 0) + + |IL.opADD: + BinOp(r1, r2); + add(r1, r2); + drop + + |IL.opSUB: + BinOp(r1, r2); + sub(r1, r2); + drop + + |IL.opADDC: + UnOp(r1); + addrc(r1, param2) + + |IL.opSUBR: + UnOp(r1); + subrc(r1, param2) + + |IL.opSUBL: + UnOp(r1); + subrc(r1, param2); + Emit(opNEG, r1, 0) + + |IL.opMULC: + UnOp(r1); + Emit(opMULC, r1, param2) + + |IL.opMUL: + BinOp(r1, r2); + Emit(opMUL, r1, r2); + drop + + |IL.opDIV: + BinOp(r1, r2); + Emit(opDIV, r1, r2); + drop + + |IL.opMOD: + BinOp(r1, r2); + Emit(opMOD, r1, r2); + drop + + |IL.opDIVR: + UnOp(r1); + Emit(opDIVC, r1, param2) + + |IL.opMODR: + UnOp(r1); + Emit(opMODC, r1, param2) + + |IL.opDIVL: + UnOp(r1); + r2 := GetAnyReg(); + movrc(r2, param2); + Emit(opDIV, r2, r1); + mov(r1, r2); + drop + + |IL.opMODL: + UnOp(r1); + r2 := GetAnyReg(); + movrc(r2, param2); + Emit(opMOD, r2, r1); + mov(r1, r2); + drop + + |IL.opEQ: + BinOp(r1, r2); + Emit(opEQ, r1, r2); + drop + + |IL.opNE: + BinOp(r1, r2); + Emit(opNE, r1, r2); + drop + + |IL.opLT: + BinOp(r1, r2); + Emit(opLT, r1, r2); + drop + + |IL.opLE: + BinOp(r1, r2); + Emit(opLE, r1, r2); + drop + + |IL.opGT: + BinOp(r1, r2); + Emit(opGT, r1, r2); + drop + + |IL.opGE: + BinOp(r1, r2); + Emit(opGE, r1, r2); + drop + + |IL.opEQC: + UnOp(r1); + Emit(opEQC, r1, param2) + + |IL.opNEC: + UnOp(r1); + Emit(opNEC, r1, param2) + + |IL.opLTC: + UnOp(r1); + Emit(opLTC, r1, param2) + + |IL.opLEC: + UnOp(r1); + Emit(opLEC, r1, param2) + + |IL.opGTC: + UnOp(r1); + Emit(opGTC, r1, param2) + + |IL.opGEC: + UnOp(r1); + Emit(opGEC, r1, param2) + + |IL.opJNZ1: + UnOp(r1); + jnz(r1, param1) + + |IL.opJG: + UnOp(r1); + Emit(opJGZ, r1, param1) + + |IL.opJNZ: + UnOp(r1); + jnz(r1, param1); + drop + + |IL.opJZ: + UnOp(r1); + Emit(opJZ, r1, param1); + drop + + |IL.opMULS: + BinOp(r1, r2); + Emit(opAND, r1, r2); + drop + + |IL.opMULSC: + UnOp(r1); + Emit(opANDC, r1, param2) + + |IL.opDIVS: + BinOp(r1, r2); + Emit(opXOR, r1, r2); + drop + + |IL.opDIVSC: + UnOp(r1); + Emit(opXORC, r1, param2) + + |IL.opADDS: + BinOp(r1, r2); + Emit(opOR, r1, r2); + drop + + |IL.opSUBS: + BinOp(r1, r2); + Emit(opNOT, r2, 0); + Emit(opAND, r1, r2); + drop + + |IL.opADDSC: + UnOp(r1); + Emit(opORC, r1, param2) + + |IL.opSUBSL: + UnOp(r1); + Emit(opNOT, r1, 0); + Emit(opANDC, r1, param2) + + |IL.opSUBSR: + UnOp(r1); + Emit(opANDC, r1, ORD(-BITS(param2))) + + |IL.opUMINS: + UnOp(r1); + Emit(opNOT, r1, 0) + + |IL.opASR: + BinOp(r1, r2); + Emit(opASR, r1, r2); + drop + + |IL.opLSL: + BinOp(r1, r2); + Emit(opLSL, r1, r2); + drop + + |IL.opROR: + BinOp(r1, r2); + Emit(opROR, r1, r2); + drop + + |IL.opLSR: + BinOp(r1, r2); + Emit(opLSR, r1, r2); + drop + + |IL.opASR1: + r2 := GetAnyReg(); + Emit(opMOVC, r2, param2); + BinOp(r1, r2); + Emit(opASR, r2, r1); + mov(r1, r2); + drop + + |IL.opLSL1: + r2 := GetAnyReg(); + Emit(opMOVC, r2, param2); + BinOp(r1, r2); + Emit(opLSL, r2, r1); + mov(r1, r2); + drop + + |IL.opROR1: + r2 := GetAnyReg(); + Emit(opMOVC, r2, param2); + BinOp(r1, r2); + Emit(opROR, r2, r1); + mov(r1, r2); + drop + + |IL.opLSR1: + r2 := GetAnyReg(); + Emit(opMOVC, r2, param2); + BinOp(r1, r2); + Emit(opLSR, r2, r1); + mov(r1, r2); + drop + + |IL.opASR2: + UnOp(r1); + Emit(opASRC, r1, param2 MOD 32) + + |IL.opLSL2: + UnOp(r1); + Emit(opLSLC, r1, param2 MOD 32) + + |IL.opROR2: + UnOp(r1); + Emit(opRORC, r1, param2 MOD 32) + + |IL.opLSR2: + UnOp(r1); + Emit(opLSRC, r1, param2 MOD 32) + + |IL.opCHR: + UnOp(r1); + Emit(opANDC, r1, 255) + + |IL.opWCHR: + UnOp(r1); + Emit(opANDC, r1, 65535) + + |IL.opABS: + UnOp(r1); + Emit(opABS, r1, 0) + + |IL.opLEN: + UnOp(r1); + drop; + EXCL(R.regs, r1); + + WHILE param2 > 0 DO + UnOp(r2); + drop; + DEC(param2) + END; + + INCL(R.regs, r1); + ASSERT(REG.GetReg(R, r1)) + + |IL.opSWITCH: + UnOp(r1); + IF param2 = 0 THEN + r2 := ACC + ELSE + r2 := R1 + END; + IF r1 # r2 THEN + ASSERT(REG.GetReg(R, r2)); + ASSERT(REG.Exchange(R, r1, r2)); + drop + END; + drop + + |IL.opENDSW: + + |IL.opCASEL: + GetAcc; + Emit(opJLA, param1, param2); + drop + + |IL.opCASER: + GetAcc; + Emit(opJGA, param1, param2); + drop + + |IL.opCASELR: + GetAcc; + Emit(opJLA, param1, param2); + Emit(opJGA, param1, cmd.param3); + drop + + |IL.opSBOOL: + BinOp(r2, r1); + Emit(opNEC, r2, 0); + str8(r1, r2); + drop; + drop + + |IL.opSBOOLC: + UnOp(r1); + Emit(opSTR8C, r1, ORD(param2 # 0)); + drop + + |IL.opINCC: + UnOp(r1); + r2 := GetAnyReg(); + ldr32(r2, r1); + addrc(r2, param2); + str32(r1, r2); + drop; + drop + + |IL.opINCCB, IL.opDECCB: + IF opcode = IL.opDECCB THEN + param2 := -param2 + END; + UnOp(r1); + r2 := GetAnyReg(); + ldr8(r2, r1); + addrc(r2, param2); + str8(r1, r2); + drop; + drop + + |IL.opINCB, IL.opDECB: + BinOp(r2, r1); + r3 := GetAnyReg(); + ldr8(r3, r1); + IF opcode = IL.opINCB THEN + add(r3, r2) + ELSE + sub(r3, r2) + END; + str8(r1, r3); + drop; + drop; + drop + + |IL.opINC, IL.opDEC: + BinOp(r2, r1); + r3 := GetAnyReg(); + ldr32(r3, r1); + IF opcode = IL.opINC THEN + add(r3, r2) + ELSE + sub(r3, r2) + END; + str32(r1, r3); + drop; + drop; + drop + + |IL.opINCL, IL.opEXCL: + BinOp(r2, r1); + IF opcode = IL.opINCL THEN + Emit(opINCL, r1, r2) + ELSE + Emit(opEXCL, r1, r2) + END; + drop; + drop + + |IL.opINCLC, IL.opEXCLC: + UnOp(r1); + r2 := GetAnyReg(); + ldr32(r2, r1); + IF opcode = IL.opINCLC THEN + Emit(opINCLC, r2, param2) + ELSE + Emit(opEXCLC, r2, param2) + END; + str32(r1, r2); + drop; + drop + + |IL.opEQB, IL.opNEB: + BinOp(r1, r2); + Emit(opNEC, r1, 0); + Emit(opNEC, r2, 0); + IF opcode = IL.opEQB THEN + Emit(opEQ, r1, r2) + ELSE + Emit(opNE, r1, r2) + END; + drop + + |IL.opCHKBYTE: + BinOp(r1, r2); + r3 := GetAnyReg(); + mov(r3, r1); + Emit(opBTC, r3, 256); + jnz(r3, param1); + drop + + |IL.opCHKIDX: + UnOp(r1); + r2 := GetAnyReg(); + mov(r2, r1); + Emit(opBTC, r2, param2); + jnz(r2, param1); + drop + + |IL.opCHKIDX2: + BinOp(r1, r2); + IF param2 # -1 THEN + r3 := GetAnyReg(); + mov(r3, r2); + Emit(opBT, r3, r1); + jnz(r3, param1); + drop + END; + INCL(R.regs, r1); + DEC(R.top); + R.stk[R.top] := r2 + + |IL.opEQP, IL.opNEP: + ProcAdr(GetAnyReg(), param1); + BinOp(r1, r2); + IF opcode = IL.opEQP THEN + Emit(opEQ, r1, r2) + ELSE + Emit(opNE, r1, r2) + END; + drop + + |IL.opSAVEP: + UnOp(r1); + r2 := GetAnyReg(); + ProcAdr(r2, param2); + str32(r1, r2); + drop; + drop + + |IL.opPUSHP: + ProcAdr(GetAnyReg(), param2) + + |IL.opPUSHT: + UnOp(r1); + r2 := GetAnyReg(); + mov(r2, r1); + subrc(r2, 4); + ldr32(r2, r2) + + |IL.opGET, IL.opGETC: + IF opcode = IL.opGET THEN + BinOp(r1, r2) + ELSIF opcode = IL.opGETC THEN + UnOp(r2); + r1 := GetAnyReg(); + movrc(r1, param1) + END; + drop; + drop; + + CASE param2 OF + |1: ldr8(r1, r1); str8(r2, r1) + |2: ldr16(r1, r1); str16(r2, r1) + |4: ldr32(r1, r1); str32(r2, r1) + END + + |IL.opNOT: + UnOp(r1); + Emit(opEQC, r1, 0) + + |IL.opORD: + UnOp(r1); + Emit(opNEC, r1, 0) + + |IL.opMIN: + BinOp(r1, r2); + Emit(opMIN, r1, r2); + drop + + |IL.opMAX: + BinOp(r1, r2); + Emit(opMAX, r1, r2); + drop + + |IL.opMINC: + UnOp(r1); + Emit(opMINC, r1, param2) + + |IL.opMAXC: + UnOp(r1); + Emit(opMAXC, r1, param2) + + |IL.opIN: + BinOp(r1, r2); + Emit(opIN, r1, r2); + drop + + |IL.opINL: + r1 := GetAnyReg(); + movrc(r1, param2); + BinOp(r2, r1); + Emit(opIN, r1, r2); + mov(r2, r1); + drop + + |IL.opINR: + UnOp(r1); + Emit(opINC, r1, param2) + + |IL.opERR: + CallRTL(IL._error, 4) + + |IL.opEQS .. IL.opGES: + PushAll(4); + pushc(opcode - IL.opEQS); + CallRTL(IL._strcmp, 5); + GetAcc + + |IL.opEQSW .. IL.opGESW: + PushAll(4); + pushc(opcode - IL.opEQSW); + CallRTL(IL._strcmpw, 5); + GetAcc + + |IL.opCOPY: + PushAll(2); + pushc(param2); + CallRTL(IL._move, 3) + + |IL.opMOVE: + PushAll(3); + CallRTL(IL._move, 3) + + |IL.opCOPYA: + PushAll(4); + pushc(param2); + CallRTL(IL._arrcpy, 5); + GetAcc + + |IL.opCOPYS: + PushAll(4); + pushc(param2); + CallRTL(IL._strcpy, 5) + + |IL.opROT: + PushAll(0); + mov(ACC, SP); + push(ACC); + pushc(param2); + CallRTL(IL._rot, 2) + + |IL.opLENGTH: + PushAll(2); + CallRTL(IL._length, 2); + GetAcc + + |IL.opLENGTHW: + PushAll(2); + CallRTL(IL._lengthw, 2); + GetAcc + + |IL.opSAVES: + UnOp(r2); + REG.PushAll_1(R); + r1 := GetAnyReg(); + StrAdr(r1, param2); + push(r1); + drop; + push(r2); + drop; + pushc(param1); + CallRTL(IL._move, 3) + + |IL.opRSET: + PushAll(2); + CallRTL(IL._set, 2); + GetAcc + + |IL.opRSETR: + PushAll(1); + pushc(param2); + CallRTL(IL._set, 2); + GetAcc + + |IL.opRSETL: + UnOp(r1); + REG.PushAll_1(R); + pushc(param2); + push(r1); + drop; + CallRTL(IL._set, 2); + GetAcc + + |IL.opRSET1: + PushAll(1); + CallRTL(IL._set1, 1); + GetAcc + + |IL.opNEW: + PushAll(1); + INC(param2, 8); + ASSERT(UTILS.Align(param2, 32)); + pushc(param2); + pushc(param1); + CallRTL(IL._new, 3) + + |IL.opTYPEGP: + UnOp(r1); + PushAll(0); + push(r1); + pushc(param2); + CallRTL(IL._guard, 2); + GetAcc + + |IL.opIS: + PushAll(1); + pushc(param2); + CallRTL(IL._is, 2); + GetAcc + + |IL.opISREC: + PushAll(2); + pushc(param2); + CallRTL(IL._guardrec, 3); + GetAcc + + |IL.opTYPEGR: + PushAll(1); + pushc(param2); + CallRTL(IL._guardrec, 2); + GetAcc + + |IL.opTYPEGD: + UnOp(r1); + PushAll(0); + subrc(r1, 4); + ldr32(r1, r1); + push(r1); + pushc(param2); + CallRTL(IL._guardrec, 2); + GetAcc + + |IL.opCASET: + push(R1); + push(R1); + pushc(param2); + CallRTL(IL._guardrec, 2); + pop(R1); + jnz(ACC, param1) + + |IL.opCONSTF: + movrc(GetAnyReg(), UTILS.d2s(cmd.float)) + + |IL.opMULF: + PushAll(2); + CallRTL(IL._fmul, 2); + GetAcc + + |IL.opDIVF: + PushAll(2); + CallRTL(IL._fdiv, 2); + GetAcc + + |IL.opDIVFI: + PushAll(2); + CallRTL(IL._fdivi, 2); + GetAcc + + |IL.opADDF: + PushAll(2); + CallRTL(IL._fadd, 2); + GetAcc + + |IL.opSUBFI: + PushAll(2); + CallRTL(IL._fsubi, 2); + GetAcc + + |IL.opSUBF: + PushAll(2); + CallRTL(IL._fsub, 2); + GetAcc + + |IL.opEQF..IL.opGEF: + PushAll(2); + pushc(opcode - IL.opEQF); + CallRTL(IL._fcmp, 3); + GetAcc + + |IL.opFLOOR: + PushAll(1); + CallRTL(IL._floor, 1); + GetAcc + + |IL.opFLT: + PushAll(1); + CallRTL(IL._flt, 1); + GetAcc + + |IL.opUMINF: + UnOp(r1); + Emit(opXORC, r1, ORD({31})) + + |IL.opFABS: + UnOp(r1); + Emit(opANDC, r1, ORD({0..30})) + + |IL.opINF: + movrc(GetAnyReg(), inf) + + |IL.opPUSHF: + UnOp(r1); + push(r1); + drop + + |IL.opPACK: + PushAll(2); + CallRTL(IL._pack, 2) + + |IL.opPACKC: + PushAll(1); + pushc(param2); + CallRTL(IL._pack, 2) + + |IL.opUNPK: + PushAll(2); + CallRTL(IL._unpk, 2) + + |IL.opCODE: + OutInt(param2) + + END; + + cmd := cmd.next(IL.COMMAND) + END; + + ASSERT(R.pushed = 0); + ASSERT(R.top = -1) +END translate; + + +PROCEDURE prolog; +BEGIN + Emit(opLEA, SP + LStack * 256, 0); + Emit(opLEA, ACC + LTypes * 256, 0); + push(ACC); + Emit(opLEA, ACC + LHeap * 256, 0); + push(ACC); + pushc(CHL.Length(IL.codes.types)); + CallRTL(IL._init, 3) +END prolog; + + +PROCEDURE epilog (ram: INTEGER); +VAR + tcount, dcount, i, offTypes, offStrings, szData, szGlobal, szHeapStack: INTEGER; + +BEGIN + Emit(opSTOP, 0, 0); + + offTypes := count; + + tcount := CHL.Length(IL.codes.types); + FOR i := 0 TO tcount - 1 DO + OutInt(CHL.GetInt(IL.codes.types, i)) + END; + + offStrings := count; + dcount := CHL.Length(IL.codes.data); + FOR i := 0 TO dcount - 1 DO + OutByte(CHL.GetByte(IL.codes.data, i)) + END; + + IF dcount MOD 4 # 0 THEN + i := 4 - dcount MOD 4; + WHILE i > 0 DO + OutByte(0); + DEC(i) + END + END; + + szData := count - offTypes; + szGlobal := (IL.codes.bss DIV 4 + 1) * 4; + szHeapStack := ram - szData - szGlobal; + + OutInt(offTypes); + OutInt(offStrings); + OutInt(szGlobal DIV 4); + OutInt(szHeapStack DIV 4); + FOR i := 1 TO 8 DO + OutInt(0) + END +END epilog; + + +PROCEDURE CodeGen* (outname: ARRAY OF CHAR; target: INTEGER; options: PROG.OPTIONS); +CONST + minRAM = 32*1024; + maxRAM = 256*1024; + +VAR + szData, szRAM: INTEGER; + +BEGIN + szData := (CHL.Length(IL.codes.types) + CHL.Length(IL.codes.data) DIV 4 + IL.codes.bss DIV 4 + 2) * 4; + szRAM := MIN(MAX(options.ram, minRAM), maxRAM) * 1024; + + IF szRAM - szData < 1024*1024 THEN + ERRORS.Error(208) + END; + + count := 0; + WR.Create(outname); + + REG.Init(R, push, pop, mov, xchg, NIL, NIL, GPRs, {}); + + prolog; + translate; + epilog(szRAM); + + WR.Close +END CodeGen; + + +END RVM32I. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/SCAN.ob07 b/programs/develop/oberon07/Source/SCAN.ob07 index 029b2f34d..c1c95571f 100644 --- a/programs/develop/oberon07/Source/SCAN.ob07 +++ b/programs/develop/oberon07/Source/SCAN.ob07 @@ -1,13 +1,13 @@ (* BSD 2-Clause License - Copyright (c) 2018-2019, Anton Krotov + Copyright (c) 2018-2020, Anton Krotov All rights reserved. *) MODULE SCAN; -IMPORT TXT := TEXTDRV, AVL := AVLTREES, ARITH, S := STRINGS; +IMPORT TXT := TEXTDRV, AVL := AVLTREES, ARITH, S := STRINGS, ERRORS, LISTS; CONST @@ -48,6 +48,12 @@ TYPE LEXSTR* = ARRAY LEXLEN OF CHAR; + DEF = POINTER TO RECORD (LISTS.ITEM) + + ident: LEXSTR + + END; + IDENT* = POINTER TO RECORD (AVL.DATA) s*: LEXSTR; @@ -88,7 +94,9 @@ VAR NewIdent: IDENT; - upto: BOOLEAN; + upto, LowerCase, _if: BOOLEAN; + + def: LISTS.LIST; PROCEDURE nodecmp (a, b: AVL.DATA): INTEGER; @@ -166,7 +174,7 @@ PROCEDURE number (text: TXT.TEXT; VAR lex: LEX); VAR c: CHAR; hex: BOOLEAN; - error: INTEGER; + error, sym: INTEGER; BEGIN c := text.peak; @@ -174,7 +182,7 @@ BEGIN error := 0; - lex.sym := lxINTEGER; + sym := lxINTEGER; hex := FALSE; WHILE S.digit(c) DO @@ -191,26 +199,26 @@ BEGIN IF c = "H" THEN putchar(lex, c); TXT.next(text); - lex.sym := lxHEX + sym := lxHEX ELSIF c = "X" THEN putchar(lex, c); TXT.next(text); - lex.sym := lxCHAR + sym := lxCHAR ELSIF c = "." THEN IF hex THEN - lex.sym := lxERROR01 + sym := lxERROR01 ELSE c := nextc(text); IF c # "." THEN putchar(lex, "."); - lex.sym := lxFLOAT + sym := lxFLOAT ELSE - lex.sym := lxINTEGER; + sym := lxINTEGER; text.peak := 7FX; upto := TRUE END; @@ -235,7 +243,7 @@ BEGIN c := nextc(text) END ELSE - lex.sym := lxERROR02 + sym := lxERROR02 END END @@ -243,31 +251,32 @@ BEGIN END ELSIF hex THEN - lex.sym := lxERROR01 + sym := lxERROR01 END; - IF lex.over & (lex.sym >= 0) THEN - lex.sym := lxERROR07 + IF lex.over & (sym >= 0) THEN + sym := lxERROR07 END; - IF lex.sym = lxINTEGER THEN + IF sym = lxINTEGER THEN ARITH.iconv(lex.s, lex.value, error) - ELSIF (lex.sym = lxHEX) OR (lex.sym = lxCHAR) THEN + ELSIF (sym = lxHEX) OR (sym = lxCHAR) THEN ARITH.hconv(lex.s, lex.value, error) - ELSIF lex.sym = lxFLOAT THEN + ELSIF sym = lxFLOAT THEN ARITH.fconv(lex.s, lex.value, error) END; CASE error OF |0: - |1: lex.sym := lxERROR08 - |2: lex.sym := lxERROR09 - |3: lex.sym := lxERROR10 - |4: lex.sym := lxERROR11 - |5: lex.sym := lxERROR12 - END + |1: sym := lxERROR08 + |2: sym := lxERROR09 + |3: sym := lxERROR10 + |4: sym := lxERROR11 + |5: sym := lxERROR12 + END; + lex.sym := sym END number; @@ -349,115 +358,120 @@ END comment; PROCEDURE delimiter (text: TXT.TEXT; VAR lex: LEX; c: CHAR); +VAR + sym: INTEGER; + BEGIN putchar(lex, c); c := nextc(text); CASE lex.s[0] OF |"+": - lex.sym := lxPLUS + sym := lxPLUS |"-": - lex.sym := lxMINUS + sym := lxMINUS |"*": - lex.sym := lxMUL + sym := lxMUL |"/": - lex.sym := lxSLASH; + sym := lxSLASH; IF c = "/" THEN - lex.sym := lxCOMMENT; + sym := lxCOMMENT; REPEAT TXT.next(text) UNTIL text.eol OR text.eof END |"~": - lex.sym := lxNOT + sym := lxNOT |"&": - lex.sym := lxAND + sym := lxAND |".": - lex.sym := lxPOINT; + sym := lxPOINT; IF c = "." THEN - lex.sym := lxRANGE; + sym := lxRANGE; putchar(lex, c); TXT.next(text) END |",": - lex.sym := lxCOMMA + sym := lxCOMMA |";": - lex.sym := lxSEMI + sym := lxSEMI |"|": - lex.sym := lxBAR + sym := lxBAR |"(": - lex.sym := lxLROUND; + sym := lxLROUND; IF c = "*" THEN - lex.sym := lxCOMMENT; + sym := lxCOMMENT; TXT.next(text); comment(text) END |"[": - lex.sym := lxLSQUARE + sym := lxLSQUARE |"{": - lex.sym := lxLCURLY + sym := lxLCURLY |"^": - lex.sym := lxCARET + sym := lxCARET |"=": - lex.sym := lxEQ + sym := lxEQ |"#": - lex.sym := lxNE + sym := lxNE |"<": - lex.sym := lxLT; + sym := lxLT; IF c = "=" THEN - lex.sym := lxLE; + sym := lxLE; putchar(lex, c); TXT.next(text) END |">": - lex.sym := lxGT; + sym := lxGT; IF c = "=" THEN - lex.sym := lxGE; + sym := lxGE; putchar(lex, c); TXT.next(text) END |":": - lex.sym := lxCOLON; + sym := lxCOLON; IF c = "=" THEN - lex.sym := lxASSIGN; + sym := lxASSIGN; putchar(lex, c); TXT.next(text) END |")": - lex.sym := lxRROUND + sym := lxRROUND |"]": - lex.sym := lxRSQUARE + sym := lxRSQUARE |"}": - lex.sym := lxRCURLY + sym := lxRCURLY - END + END; + + lex.sym := sym END delimiter; @@ -466,6 +480,107 @@ PROCEDURE Next* (text: SCANNER; VAR lex: LEX); VAR c: CHAR; + + PROCEDURE check (cond: BOOLEAN; text: SCANNER; lex: LEX; errno: INTEGER); + BEGIN + IF ~cond THEN + ERRORS.ErrorMsg(text.fname, lex.pos.line, lex.pos.col, errno) + END + END check; + + + PROCEDURE IsDef (str: ARRAY OF CHAR): BOOLEAN; + VAR + cur: DEF; + + BEGIN + cur := def.first(DEF); + WHILE (cur # NIL) & (cur.ident # str) DO + cur := cur.next(DEF) + END + + RETURN cur # NIL + END IsDef; + + + PROCEDURE Skip (text: SCANNER); + VAR + i: INTEGER; + + BEGIN + i := 0; + WHILE (i <= text.ifc) & ~text._skip[i] DO + INC(i) + END; + text.skip := i <= text.ifc + END Skip; + + + PROCEDURE prep_if (text: SCANNER; VAR lex: LEX); + VAR + skip: BOOLEAN; + + BEGIN + INC(text.ifc); + text._elsif[text.ifc] := lex.sym = lxELSIF; + IF lex.sym = lxIF THEN + INC(text.elsec); + text._else[text.elsec] := FALSE + END; + _if := TRUE; + skip := TRUE; + text.skip := FALSE; + + Next(text, lex); + check(lex.sym = lxLROUND, text, lex, 64); + + Next(text, lex); + check(lex.sym = lxIDENT, text, lex, 22); + + REPEAT + IF IsDef(lex.s) THEN + skip := FALSE + END; + + Next(text, lex); + IF lex.sym = lxBAR THEN + Next(text, lex); + check(lex.sym = lxIDENT, text, lex, 22) + ELSE + check(lex.sym = lxRROUND, text, lex, 33) + END + UNTIL lex.sym = lxRROUND; + + _if := FALSE; + text._skip[text.ifc] := skip; + Skip(text); + Next(text, lex) + END prep_if; + + + PROCEDURE prep_end (text: SCANNER; VAR lex: LEX); + BEGIN + check(text.ifc > 0, text, lex, 118); + IF lex.sym = lxEND THEN + WHILE text._elsif[text.ifc] DO + DEC(text.ifc) + END; + DEC(text.ifc); + DEC(text.elsec) + ELSIF (lex.sym = lxELSE) OR (lex.sym = lxELSIF) THEN + check(~text._else[text.elsec], text, lex, 118); + text._skip[text.ifc] := ~text._skip[text.ifc]; + text._else[text.elsec] := lex.sym = lxELSE + END; + Skip(text); + IF lex.sym = lxELSIF THEN + prep_if(text, lex) + ELSE + Next(text, lex) + END + END prep_end; + + BEGIN REPEAT @@ -490,8 +605,26 @@ BEGIN string(text, lex, c) ELSIF delimiters[ORD(c)] THEN delimiter(text, lex, c) + ELSIF c = "$" THEN + IF S.letter(nextc(text)) THEN + ident(text, lex); + IF lex.sym = lxIF THEN + IF ~_if THEN + prep_if(text, lex) + END + ELSIF (lex.sym = lxEND) OR (lex.sym = lxELSE) OR (lex.sym = lxELSIF) THEN + IF ~_if THEN + prep_end(text, lex) + END + ELSE + check(FALSE, text, lex, 119) + END + ELSE + check(FALSE, text, lex, 119) + END ELSIF c = 0X THEN lex.sym := lxEOF; + text.skip := FALSE; IF text.eof THEN INC(lex.pos.col) END @@ -514,7 +647,7 @@ BEGIN lex.error := 0 END - UNTIL lex.sym # lxCOMMENT + UNTIL (lex.sym # lxCOMMENT) & ~text.skip END Next; @@ -530,7 +663,7 @@ BEGIN END close; -PROCEDURE init; +PROCEDURE init* (lower: BOOLEAN); VAR i: INTEGER; delim: ARRAY 23 OF CHAR; @@ -539,15 +672,23 @@ VAR PROCEDURE enterkw (key: INTEGER; kw: LEXSTR); VAR id: IDENT; + upper: LEXSTR; BEGIN - id := enterid(kw); + IF LowerCase THEN + id := enterid(kw); + id.key := key + END; + upper := kw; + S.UpCase(upper); + id := enterid(upper); id.key := key END enterkw; BEGIN upto := FALSE; + LowerCase := lower; FOR i := 0 TO 255 DO delimiters[i] := FALSE @@ -567,43 +708,54 @@ BEGIN idents := NIL; - enterkw(lxARRAY, "ARRAY"); - enterkw(lxBEGIN, "BEGIN"); - enterkw(lxBY, "BY"); - enterkw(lxCASE, "CASE"); - enterkw(lxCONST, "CONST"); - enterkw(lxDIV, "DIV"); - enterkw(lxDO, "DO"); - enterkw(lxELSE, "ELSE"); - enterkw(lxELSIF, "ELSIF"); - enterkw(lxEND, "END"); - enterkw(lxFALSE, "FALSE"); - enterkw(lxFOR, "FOR"); - enterkw(lxIF, "IF"); - enterkw(lxIMPORT, "IMPORT"); - enterkw(lxIN, "IN"); - enterkw(lxIS, "IS"); - enterkw(lxMOD, "MOD"); - enterkw(lxMODULE, "MODULE"); - enterkw(lxNIL, "NIL"); - enterkw(lxOF, "OF"); - enterkw(lxOR, "OR"); - enterkw(lxPOINTER, "POINTER"); - enterkw(lxPROCEDURE, "PROCEDURE"); - enterkw(lxRECORD, "RECORD"); - enterkw(lxREPEAT, "REPEAT"); - enterkw(lxRETURN, "RETURN"); - enterkw(lxTHEN, "THEN"); - enterkw(lxTO, "TO"); - enterkw(lxTRUE, "TRUE"); - enterkw(lxTYPE, "TYPE"); - enterkw(lxUNTIL, "UNTIL"); - enterkw(lxVAR, "VAR"); - enterkw(lxWHILE, "WHILE") + enterkw(lxARRAY, "array"); + enterkw(lxBEGIN, "begin"); + enterkw(lxBY, "by"); + enterkw(lxCASE, "case"); + enterkw(lxCONST, "const"); + enterkw(lxDIV, "div"); + enterkw(lxDO, "do"); + enterkw(lxELSE, "else"); + enterkw(lxELSIF, "elsif"); + enterkw(lxEND, "end"); + enterkw(lxFALSE, "false"); + enterkw(lxFOR, "for"); + enterkw(lxIF, "if"); + enterkw(lxIMPORT, "import"); + enterkw(lxIN, "in"); + enterkw(lxIS, "is"); + enterkw(lxMOD, "mod"); + enterkw(lxMODULE, "module"); + enterkw(lxNIL, "nil"); + enterkw(lxOF, "of"); + enterkw(lxOR, "or"); + enterkw(lxPOINTER, "pointer"); + enterkw(lxPROCEDURE, "procedure"); + enterkw(lxRECORD, "record"); + enterkw(lxREPEAT, "repeat"); + enterkw(lxRETURN, "return"); + enterkw(lxTHEN, "then"); + enterkw(lxTO, "to"); + enterkw(lxTRUE, "true"); + enterkw(lxTYPE, "type"); + enterkw(lxUNTIL, "until"); + enterkw(lxVAR, "var"); + enterkw(lxWHILE, "while") END init; +PROCEDURE NewDef* (str: ARRAY OF CHAR); +VAR + item: DEF; + BEGIN - init + NEW(item); + COPY(str, item.ident); + LISTS.push(def, item) +END NewDef; + + +BEGIN + def := LISTS.create(NIL) END SCAN. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/STATEMENTS.ob07 b/programs/develop/oberon07/Source/STATEMENTS.ob07 index 269719d78..a873af1b4 100644 --- a/programs/develop/oberon07/Source/STATEMENTS.ob07 +++ b/programs/develop/oberon07/Source/STATEMENTS.ob07 @@ -9,7 +9,7 @@ MODULE STATEMENTS; IMPORT - PARS, PROG, SCAN, ARITH, STRINGS, LISTS, IL, X86, AMD64, MSP430, THUMB, + PARS, PROG, SCAN, ARITH, STRINGS, LISTS, IL, X86, AMD64, MSP430, THUMB, RVM32I, ERRORS, UTILS, AVL := AVLTREES, CONSOLE, C := COLLECTIONS, TARGETS; @@ -48,7 +48,7 @@ TYPE variant, self: INTEGER; - type: PROG.TYPE_; + _type: PROG._TYPE; prev: CASE_LABEL @@ -75,7 +75,7 @@ VAR CPU: INTEGER; - tINTEGER, tBYTE, tCHAR, tWCHAR, tSET, tBOOLEAN, tREAL: PROG.TYPE_; + tINTEGER, tBYTE, tCHAR, tWCHAR, tSET, tBOOLEAN, tREAL: PROG._TYPE; PROCEDURE isExpr (e: PARS.EXPR): BOOLEAN; @@ -89,17 +89,17 @@ END isVar; PROCEDURE isBoolean (e: PARS.EXPR): BOOLEAN; - RETURN isExpr(e) & (e.type = tBOOLEAN) + RETURN isExpr(e) & (e._type = tBOOLEAN) END isBoolean; PROCEDURE isInteger (e: PARS.EXPR): BOOLEAN; - RETURN isExpr(e) & (e.type = tINTEGER) + RETURN isExpr(e) & (e._type = tINTEGER) END isInteger; PROCEDURE isByte (e: PARS.EXPR): BOOLEAN; - RETURN isExpr(e) & (e.type = tBYTE) + RETURN isExpr(e) & (e._type = tBYTE) END isByte; @@ -109,42 +109,42 @@ END isInt; PROCEDURE isReal (e: PARS.EXPR): BOOLEAN; - RETURN isExpr(e) & (e.type = tREAL) + RETURN isExpr(e) & (e._type = tREAL) END isReal; PROCEDURE isSet (e: PARS.EXPR): BOOLEAN; - RETURN isExpr(e) & (e.type = tSET) + RETURN isExpr(e) & (e._type = tSET) END isSet; PROCEDURE isString (e: PARS.EXPR): BOOLEAN; - RETURN (e.obj = eCONST) & (e.type.typ IN {PROG.tSTRING, PROG.tCHAR}) + RETURN (e.obj = eCONST) & (e._type.typ IN {PROG.tSTRING, PROG.tCHAR}) END isString; PROCEDURE isStringW (e: PARS.EXPR): BOOLEAN; - RETURN (e.obj = eCONST) & (e.type.typ IN {PROG.tSTRING, PROG.tCHAR, PROG.tWCHAR}) + RETURN (e.obj = eCONST) & (e._type.typ IN {PROG.tSTRING, PROG.tCHAR, PROG.tWCHAR}) END isStringW; PROCEDURE isChar (e: PARS.EXPR): BOOLEAN; - RETURN isExpr(e) & (e.type = tCHAR) + RETURN isExpr(e) & (e._type = tCHAR) END isChar; PROCEDURE isCharW (e: PARS.EXPR): BOOLEAN; - RETURN isExpr(e) & (e.type = tWCHAR) + RETURN isExpr(e) & (e._type = tWCHAR) END isCharW; PROCEDURE isPtr (e: PARS.EXPR): BOOLEAN; - RETURN isExpr(e) & (e.type.typ = PROG.tPOINTER) + RETURN isExpr(e) & (e._type.typ = PROG.tPOINTER) END isPtr; PROCEDURE isRec (e: PARS.EXPR): BOOLEAN; - RETURN isExpr(e) & (e.type.typ = PROG.tRECORD) + RETURN isExpr(e) & (e._type.typ = PROG.tRECORD) END isRec; @@ -154,27 +154,27 @@ END isRecPtr; PROCEDURE isArr (e: PARS.EXPR): BOOLEAN; - RETURN isExpr(e) & (e.type.typ = PROG.tARRAY) + RETURN isExpr(e) & (e._type.typ = PROG.tARRAY) END isArr; PROCEDURE isProc (e: PARS.EXPR): BOOLEAN; - RETURN isExpr(e) & (e.type.typ = PROG.tPROCEDURE) OR (e.obj IN {ePROC, eIMP}) + RETURN isExpr(e) & (e._type.typ = PROG.tPROCEDURE) OR (e.obj IN {ePROC, eIMP}) END isProc; PROCEDURE isNil (e: PARS.EXPR): BOOLEAN; - RETURN e.type.typ = PROG.tNIL + RETURN e._type.typ = PROG.tNIL END isNil; PROCEDURE isCharArray (e: PARS.EXPR): BOOLEAN; - RETURN isArr(e) & (e.type.base = tCHAR) + RETURN isArr(e) & (e._type.base = tCHAR) END isCharArray; PROCEDURE isCharArrayW (e: PARS.EXPR): BOOLEAN; - RETURN isArr(e) & (e.type.base = tWCHAR) + RETURN isArr(e) & (e._type.base = tWCHAR) END isCharArrayW; @@ -204,7 +204,7 @@ VAR BEGIN ASSERT(isString(e)); - IF e.type = tCHAR THEN + IF e._type = tCHAR THEN res := 1 ELSE res := LENGTH(e.value.string(SCAN.IDENT).s) @@ -237,7 +237,7 @@ VAR BEGIN ASSERT(isStringW(e)); - IF e.type.typ IN {PROG.tCHAR, PROG.tWCHAR} THEN + IF e._type.typ IN {PROG.tCHAR, PROG.tWCHAR} THEN res := 1 ELSE res := _length(e.value.string(SCAN.IDENT).s) @@ -257,18 +257,18 @@ END StrToWChar; PROCEDURE isStringW1 (e: PARS.EXPR): BOOLEAN; - RETURN (e.obj = eCONST) & isString(e) & (utf8strlen(e) = 1) & (strlen(e) > 1) + RETURN isString(e) & (utf8strlen(e) = 1) & (strlen(e) > 1) END isStringW1; -PROCEDURE assigncomp (e: PARS.EXPR; t: PROG.TYPE_): BOOLEAN; +PROCEDURE assigncomp (e: PARS.EXPR; t: PROG._TYPE): BOOLEAN; VAR res: BOOLEAN; BEGIN IF isExpr(e) OR (e.obj IN {ePROC, eIMP}) THEN - IF t = e.type THEN + IF t = e._type THEN res := TRUE ELSIF isInt(e) & (t.typ IN {PROG.tBYTE, PROG.tINTEGER}) THEN IF (e.obj = eCONST) & (t = tBYTE) THEN @@ -279,10 +279,10 @@ BEGIN ELSIF (e.obj = eCONST) & isChar(e) & (t = tWCHAR) OR isStringW1(e) & (t = tWCHAR) - OR PROG.isBaseOf(t, e.type) - OR ~PROG.isOpenArray(t) & ~PROG.isOpenArray(e.type) & PROG.isTypeEq(t, e.type) + OR PROG.isBaseOf(t, e._type) + OR ~PROG.isOpenArray(t) & ~PROG.isOpenArray(e._type) & PROG.isTypeEq(t, e._type) OR isNil(e) & (t.typ IN {PROG.tPOINTER, PROG.tPROCEDURE}) - OR PROG.arrcomp(e.type, t) + OR PROG.arrcomp(e._type, t) OR isString(e) & (t.typ = PROG.tARRAY) & (t.base = tCHAR) & (t.length > strlen(e)) OR isStringW(e) & (t.typ = PROG.tARRAY) & (t.base = tWCHAR) & (t.length > utf8strlen(e)) THEN @@ -331,9 +331,9 @@ BEGIN END; offset := string.offsetW ELSE - IF e.type.typ IN {PROG.tWCHAR, PROG.tCHAR} THEN + IF e._type.typ IN {PROG.tWCHAR, PROG.tCHAR} THEN offset := IL.putstrW1(ARITH.Int(e.value)) - ELSE (* e.type.typ = PROG.tSTRING *) + ELSE (* e._type.typ = PROG.tSTRING *) string := e.value.string(SCAN.IDENT); IF string.offsetW = -1 THEN string.offsetW := IL.putstrW(string.s); @@ -358,7 +358,17 @@ BEGIN END CheckRange; -PROCEDURE assign (e: PARS.EXPR; VarType: PROG.TYPE_; line: INTEGER): BOOLEAN; +PROCEDURE Float (parser: PARS.PARSER; e: PARS.EXPR); +VAR + pos: PARS.POSITION; + +BEGIN + getpos(parser, pos); + IL.Float(ARITH.Float(e.value), pos.line, pos.col) +END Float; + + +PROCEDURE assign (parser: PARS.PARSER; e: PARS.EXPR; VarType: PROG._TYPE; line: INTEGER): BOOLEAN; VAR res: BOOLEAN; label: INTEGER; @@ -366,14 +376,14 @@ VAR BEGIN IF isExpr(e) OR (e.obj IN {ePROC, eIMP}) THEN res := TRUE; - IF PROG.arrcomp(e.type, VarType) THEN + IF PROG.arrcomp(e._type, VarType) THEN IF ~PROG.isOpenArray(VarType) THEN IL.Const(VarType.length) END; IL.AddCmd(IL.opCOPYA, VarType.base.size); label := IL.NewLabel(); - IL.AddJmpCmd(IL.opJE, label); + IL.AddJmpCmd(IL.opJNZ, label); IL.OnError(line, errCOPY); IL.SetLabel(label) @@ -414,7 +424,7 @@ BEGIN END ELSIF isReal(e) & (VarType = tREAL) THEN IF e.obj = eCONST THEN - IL.Float(ARITH.Float(e.value)) + Float(parser, e) END; IL.savef(e.obj = eCONST) ELSIF isChar(e) & (VarType = tCHAR) THEN @@ -433,19 +443,19 @@ BEGIN ELSE IL.AddCmd0(IL.opSAVE16) END - ELSIF PROG.isBaseOf(VarType, e.type) THEN + ELSIF PROG.isBaseOf(VarType, e._type) THEN IF VarType.typ = PROG.tPOINTER THEN IL.AddCmd0(IL.opSAVE) ELSE IL.AddCmd(IL.opCOPY, VarType.size) END - ELSIF (e.type.typ = PROG.tCARD32) & (VarType.typ = PROG.tCARD32) THEN + ELSIF (e._type.typ = PROG.tCARD32) & (VarType.typ = PROG.tCARD32) THEN IL.AddCmd0(IL.opSAVE32) - ELSIF ~PROG.isOpenArray(VarType) & ~PROG.isOpenArray(e.type) & PROG.isTypeEq(VarType, e.type) THEN + ELSIF ~PROG.isOpenArray(VarType) & ~PROG.isOpenArray(e._type) & PROG.isTypeEq(VarType, e._type) THEN IF e.obj = ePROC THEN IL.AssignProc(e.ident.proc.label) ELSIF e.obj = eIMP THEN - IL.AssignImpProc(e.ident.import) + IL.AssignImpProc(e.ident._import) ELSE IF VarType.typ = PROG.tPROCEDURE THEN IL.AddCmd0(IL.opSAVE) @@ -481,11 +491,11 @@ VAR PROCEDURE arrcomp (e: PARS.EXPR; p: PROG.PARAM): BOOLEAN; VAR - t1, t2: PROG.TYPE_; + t1, t2: PROG._TYPE; BEGIN - t1 := p.type; - t2 := e.type; + t1 := p._type; + t2 := e._type; WHILE (t2.typ = PROG.tARRAY) & PROG.isOpenArray(t1) DO t1 := t1.base; t2 := t2.base @@ -495,7 +505,7 @@ VAR END arrcomp; - PROCEDURE ArrLen (t: PROG.TYPE_; n: INTEGER): INTEGER; + PROCEDURE ArrLen (t: PROG._TYPE; n: INTEGER): INTEGER; VAR res: INTEGER; @@ -510,7 +520,7 @@ VAR END ArrLen; - PROCEDURE OpenArray (t, t2: PROG.TYPE_); + PROCEDURE OpenArray (t, t2: PROG._TYPE); VAR n, d1, d2: INTEGER; @@ -547,8 +557,8 @@ BEGIN IF p.vPar THEN PARS.check(isVar(e), pos, 93); - IF p.type.typ = PROG.tRECORD THEN - PARS.check(PROG.isBaseOf(p.type, e.type), pos, 66); + IF p._type.typ = PROG.tRECORD THEN + PARS.check(PROG.isBaseOf(p._type, e._type), pos, 66); IF e.obj = eVREC THEN IF e.ident # NIL THEN IL.AddCmd(IL.opVADR, e.ident.offset - 1) @@ -556,30 +566,30 @@ BEGIN IL.AddCmd0(IL.opPUSHT) END ELSE - IL.Const(e.type.num) + IL.Const(e._type.num) END; IL.AddCmd(IL.opPARAM, 2) - ELSIF PROG.isOpenArray(p.type) THEN + ELSIF PROG.isOpenArray(p._type) THEN PARS.check(arrcomp(e, p), pos, 66); - OpenArray(e.type, p.type) + OpenArray(e._type, p._type) ELSE - PARS.check(PROG.isTypeEq(e.type, p.type), pos, 66); + PARS.check(PROG.isTypeEq(e._type, p._type), pos, 66); IL.Param1 END; PARS.check(~e.readOnly, pos, 94) ELSE PARS.check(isExpr(e) OR isProc(e), pos, 66); - IF PROG.isOpenArray(p.type) THEN - IF e.type.typ = PROG.tARRAY THEN + IF PROG.isOpenArray(p._type) THEN + IF e._type.typ = PROG.tARRAY THEN PARS.check(arrcomp(e, p), pos, 66); - OpenArray(e.type, p.type) - ELSIF isString(e) & (p.type.typ = PROG.tARRAY) & (p.type.base = tCHAR) THEN + OpenArray(e._type, p._type) + ELSIF isString(e) & (p._type.typ = PROG.tARRAY) & (p._type.base = tCHAR) THEN IL.StrAdr(String(e)); IL.Param1; IL.Const(strlen(e) + 1); IL.Param1 - ELSIF isStringW(e) & (p.type.typ = PROG.tARRAY) & (p.type.base = tWCHAR) THEN + ELSIF isStringW(e) & (p._type.typ = PROG.tARRAY) & (p._type.base = tWCHAR) THEN IL.StrAdr(StringW(e)); IL.Param1; IL.Const(utf8strlen(e) + 1); @@ -588,31 +598,31 @@ BEGIN PARS.error(pos, 66) END ELSE - PARS.check(~PROG.isOpenArray(e.type), pos, 66); - PARS.check(assigncomp(e, p.type), pos, 66); + PARS.check(~PROG.isOpenArray(e._type), pos, 66); + PARS.check(assigncomp(e, p._type), pos, 66); IF e.obj = eCONST THEN - IF e.type = tREAL THEN - IL.Float(ARITH.Float(e.value)); - IL.pushf - ELSIF e.type.typ = PROG.tNIL THEN + IF e._type = tREAL THEN + Float(parser, e); + IL.AddCmd0(IL.opPUSHF) + ELSIF e._type.typ = PROG.tNIL THEN IL.Const(0); IL.Param1 - ELSIF isStringW1(e) & (p.type = tWCHAR) THEN + ELSIF isStringW1(e) & (p._type = tWCHAR) THEN IL.Const(StrToWChar(e.value.string(SCAN.IDENT).s)); IL.Param1 - ELSIF (e.type.typ = PROG.tSTRING) OR - (e.type.typ IN {PROG.tCHAR, PROG.tWCHAR}) & (p.type.typ = PROG.tARRAY) & (p.type.base.typ IN {PROG.tCHAR, PROG.tWCHAR}) THEN - IF p.type.base = tCHAR THEN + ELSIF (e._type.typ = PROG.tSTRING) OR + (e._type.typ IN {PROG.tCHAR, PROG.tWCHAR}) & (p._type.typ = PROG.tARRAY) & (p._type.base.typ IN {PROG.tCHAR, PROG.tWCHAR}) THEN + IF p._type.base = tCHAR THEN stroffs := String(e); IL.StrAdr(stroffs); - IF (CPU = TARGETS.cpuMSP430) & (p.type.size - strlen(e) - 1 > MSP430.IntVectorSize) THEN + IF (CPU = TARGETS.cpuMSP430) & (p._type.size - strlen(e) - 1 > MSP430.IntVectorSize) THEN ERRORS.WarningMsg(pos.line, pos.col, 0) END ELSE (* WCHAR *) stroffs := StringW(e); IL.StrAdr(stroffs) END; - IL.set_dmin(stroffs + p.type.size); + IL.set_dmin(stroffs + p._type.size); IL.Param1 ELSE LoadConst(e); @@ -623,12 +633,12 @@ BEGIN IL.PushProc(e.ident.proc.label); IL.Param1 ELSIF e.obj = eIMP THEN - IL.PushImpProc(e.ident.import); + IL.PushImpProc(e.ident._import); IL.Param1 - ELSIF isExpr(e) & (e.type = tREAL) THEN - IL.pushf + ELSIF isExpr(e) & (e._type = tREAL) THEN + IL.AddCmd0(IL.opPUSHF) ELSE - IF (p.type = tBYTE) & (e.type = tINTEGER) & (chkBYTE IN Options.checking) THEN + IF (p._type = tBYTE) & (e._type = tINTEGER) & (chkBYTE IN Options.checking) THEN CheckRange(256, pos.line, errBYTE) END; IL.Param1 @@ -651,6 +661,7 @@ VAR pos: PARS.POSITION; proc, label, + size, n, i: INTEGER; code: ARITH.VALUE; wchar, @@ -716,7 +727,8 @@ BEGIN END ELSE label := IL.NewLabel(); - IL.AddJmpCmd(IL.opJE, label); + IL.not; + IL.AndOrOpt(label); IL.OnError(pos.line, errASSERT); IL.SetLabel(label) END @@ -724,7 +736,7 @@ BEGIN |PROG.stINC, PROG.stDEC: IL.pushBegEnd(begcall, endcall); varparam(parser, pos, isInt, TRUE, e); - IF e.type = tINTEGER THEN + IF e._type = tINTEGER THEN IF parser.sym = SCAN.lxCOMMA THEN NextPos(parser, pos); IL.setlast(begcall); @@ -739,7 +751,7 @@ BEGIN ELSE IL.AddCmd(IL.opINCC, ORD(proc = PROG.stINC) * 2 - 1) END - ELSE (* e.type = tBYTE *) + ELSE (* e._type = tBYTE *) IF parser.sym = SCAN.lxCOMMA THEN NextPos(parser, pos); IL.setlast(begcall); @@ -777,9 +789,9 @@ BEGIN |PROG.stNEW: varparam(parser, pos, isPtr, TRUE, e); IF CPU = TARGETS.cpuMSP430 THEN - PARS.check(e.type.base.size + 16 < Options.ram, pos, 63) + PARS.check(e._type.base.size + 16 < Options.ram, pos, 63) END; - IL.New(e.type.base.size, e.type.base.num) + IL.New(e._type.base.size, e._type.base.num) |PROG.stDISPOSE: varparam(parser, pos, isPtr, TRUE, e); @@ -815,8 +827,8 @@ BEGIN PARS.error(pos, 66) END; - IF isCharArrayX(e) & ~PROG.isOpenArray(e.type) THEN - IL.Const(e.type.length) + IF isCharArrayX(e) & ~PROG.isOpenArray(e._type) THEN + IL.Const(e._type.length) END; PARS.checklex(parser, SCAN.lxCOMMA); @@ -832,11 +844,11 @@ BEGIN varparam(parser, pos, isCharArray, TRUE, e1) END; - wchar := e1.type.base = tWCHAR + wchar := e1._type.base = tWCHAR END; - IF ~PROG.isOpenArray(e1.type) THEN - IL.Const(e1.type.length) + IF ~PROG.isOpenArray(e1._type) THEN + IL.Const(e1._type.length) END; IL.setlast(endcall.prev(IL.COMMAND)); @@ -850,21 +862,35 @@ BEGIN IL.Const(strlen(e) + 1) END END; - IL.AddCmd(IL.opCOPYS, e1.type.base.size); + IL.AddCmd(IL.opCOPYS, e1._type.base.size); IL.popBegEnd(begcall, endcall) - |PROG.sysGET: + |PROG.sysGET, PROG.sysGET8, PROG.sysGET16, PROG.sysGET32: PExpression(parser, e); PARS.check(isInt(e), pos, 66); PARS.checklex(parser, SCAN.lxCOMMA); NextPos(parser, pos); parser.designator(parser, e2); PARS.check(isVar(e2), pos, 93); - PARS.check(e2.type.typ IN PROG.BASICTYPES + {PROG.tPOINTER, PROG.tPROCEDURE}, pos, 66); - IF e.obj = eCONST THEN - IL.AddCmd2(IL.opGETC, ARITH.Int(e.value), e2.type.size) + IF proc = PROG.sysGET THEN + PARS.check(e2._type.typ IN PROG.BASICTYPES + {PROG.tPOINTER, PROG.tPROCEDURE}, pos, 66) ELSE - IL.AddCmd(IL.opGET, e2.type.size) + PARS.check(e2._type.typ IN {PROG.tINTEGER, PROG.tBYTE, PROG.tCHAR, PROG.tSET, PROG.tWCHAR, PROG.tCARD32}, pos, 66) + END; + + CASE proc OF + |PROG.sysGET: size := e2._type.size + |PROG.sysGET8: size := 1 + |PROG.sysGET16: size := 2 + |PROG.sysGET32: size := 4 + END; + + PARS.check(size <= e2._type.size, pos, 66); + + IF e.obj = eCONST THEN + IL.AddCmd2(IL.opGETC, ARITH.Int(e.value), size) + ELSE + IL.AddCmd(IL.opGET, size) END |PROG.sysPUT, PROG.sysPUT8, PROG.sysPUT16, PROG.sysPUT32: @@ -881,39 +907,40 @@ BEGIN PARS.check(isExpr(e2), pos, 66); IF proc = PROG.sysPUT THEN - PARS.check(e2.type.typ IN PROG.BASICTYPES + {PROG.tPOINTER, PROG.tPROCEDURE}, pos, 66); + PARS.check(e2._type.typ IN PROG.BASICTYPES + {PROG.tPOINTER, PROG.tPROCEDURE}, pos, 66); IF e2.obj = eCONST THEN - IF e2.type = tREAL THEN - IL.Float(ARITH.Float(e2.value)); + IF e2._type = tREAL THEN + Float(parser, e2); IL.setlast(endcall.prev(IL.COMMAND)); IL.savef(FALSE) ELSE LoadConst(e2); IL.setlast(endcall.prev(IL.COMMAND)); - IL.SysPut(e2.type.size) + IL.SysPut(e2._type.size) END ELSE IL.setlast(endcall.prev(IL.COMMAND)); - IF e2.type = tREAL THEN + IF e2._type = tREAL THEN IL.savef(FALSE) - ELSIF e2.type = tBYTE THEN + ELSIF e2._type = tBYTE THEN IL.SysPut(tINTEGER.size) ELSE - IL.SysPut(e2.type.size) + IL.SysPut(e2._type.size) END END ELSIF (proc = PROG.sysPUT8) OR (proc = PROG.sysPUT16) OR (proc = PROG.sysPUT32) THEN - PARS.check(e2.type.typ IN {PROG.tINTEGER, PROG.tBYTE, PROG.tCHAR, PROG.tSET, PROG.tWCHAR, PROG.tCARD32}, pos, 66); + PARS.check(e2._type.typ IN {PROG.tINTEGER, PROG.tBYTE, PROG.tCHAR, PROG.tSET, PROG.tWCHAR, PROG.tCARD32}, pos, 66); IF e2.obj = eCONST THEN LoadConst(e2) END; IL.setlast(endcall.prev(IL.COMMAND)); CASE proc OF - |PROG.sysPUT8: IL.SysPut(1) - |PROG.sysPUT16: IL.SysPut(2) - |PROG.sysPUT32: IL.SysPut(4) - END + |PROG.sysPUT8: size := 1 + |PROG.sysPUT16: size := 2 + |PROG.sysPUT32: size := 4 + END; + IL.SysPut(size) END; IL.popBegEnd(begcall, endcall) @@ -940,7 +967,7 @@ BEGIN FOR i := 1 TO 2 DO parser.designator(parser, e); PARS.check(isVar(e), pos, 93); - n := PROG.Dim(e.type); + n := PROG.Dim(e._type); WHILE n > 0 DO IL.drop; DEC(n) @@ -961,10 +988,11 @@ BEGIN getpos(parser, pos); PARS.ConstExpression(parser, code); PARS.check(code.typ = ARITH.tINTEGER, pos, 43); - IF CPU IN {TARGETS.cpuX86, TARGETS.cpuAMD64} THEN - PARS.check(ARITH.range(code, 0, 255), pos, 42) - ELSIF CPU = TARGETS.cpuTHUMB THEN - PARS.check(ARITH.range(code, 0, 65535), pos, 110) + IF TARGETS.WordSize > TARGETS.InstrSize THEN + CASE TARGETS.InstrSize OF + |1: PARS.check(ARITH.range(code, 0, 255), pos, 42) + |2: PARS.check(ARITH.range(code, 0, 65535), pos, 110) + END END; IL.AddCmd(IL.opCODE, ARITH.getInt(code)); comma := parser.sym = SCAN.lxCOMMA; @@ -991,7 +1019,7 @@ BEGIN END; e.obj := eEXPR; - e.type := NIL + e._type := NIL ELSIF e.obj IN {eSTFUNC, eSYSFUNC} THEN @@ -1012,7 +1040,7 @@ BEGIN NextPos(parser, pos); PExpression(parser, e2); PARS.check(isInt(e2), pos, 66); - e.type := tINTEGER; + e._type := tINTEGER; IF (e.obj = eCONST) & (e2.obj = eCONST) THEN ASSERT(ARITH.opInt(e.value, e2.value, shift_minmax(proc))) ELSE @@ -1029,7 +1057,7 @@ BEGIN |PROG.stCHR: PExpression(parser, e); PARS.check(isInt(e), pos, 66); - e.type := tCHAR; + e._type := tCHAR; IF e.obj = eCONST THEN ARITH.setChar(e.value, ARITH.getInt(e.value)); PARS.check(ARITH.check(e.value), pos, 107) @@ -1044,7 +1072,7 @@ BEGIN |PROG.stWCHR: PExpression(parser, e); PARS.check(isInt(e), pos, 66); - e.type := tWCHAR; + e._type := tWCHAR; IF e.obj = eCONST THEN ARITH.setWChar(e.value, ARITH.getInt(e.value)); PARS.check(ARITH.check(e.value), pos, 101) @@ -1059,58 +1087,58 @@ BEGIN |PROG.stFLOOR: PExpression(parser, e); PARS.check(isReal(e), pos, 66); - e.type := tINTEGER; + e._type := tINTEGER; IF e.obj = eCONST THEN PARS.check(ARITH.floor(e.value), pos, 39) ELSE - IL.floor + IL.AddCmd0(IL.opFLOOR) END |PROG.stFLT: PExpression(parser, e); PARS.check(isInt(e), pos, 66); - e.type := tREAL; + e._type := tREAL; IF e.obj = eCONST THEN ARITH.flt(e.value) ELSE - PARS.check(IL.flt(), pos, 41) + IL.AddCmd2(IL.opFLT, pos.line, pos.col) END |PROG.stLEN: cmd1 := IL.getlast(); varparam(parser, pos, isArr, FALSE, e); - IF e.type.length > 0 THEN + IF e._type.length > 0 THEN cmd2 := IL.getlast(); IL.delete2(cmd1.next, cmd2); IL.setlast(cmd1); - ASSERT(ARITH.setInt(e.value, e.type.length)); + ASSERT(ARITH.setInt(e.value, e._type.length)); e.obj := eCONST ELSE - IL.len(PROG.Dim(e.type)) + IL.len(PROG.Dim(e._type)) END; - e.type := tINTEGER + e._type := tINTEGER |PROG.stLENGTH: PExpression(parser, e); IF isCharArray(e) THEN - IF e.type.length > 0 THEN - IL.Const(e.type.length) + IF e._type.length > 0 THEN + IL.Const(e._type.length) END; IL.AddCmd0(IL.opLENGTH) ELSIF isCharArrayW(e) THEN - IF e.type.length > 0 THEN - IL.Const(e.type.length) + IF e._type.length > 0 THEN + IL.Const(e._type.length) END; IL.AddCmd0(IL.opLENGTHW) ELSE PARS.error(pos, 66); END; - e.type := tINTEGER + e._type := tINTEGER |PROG.stODD: PExpression(parser, e); PARS.check(isInt(e), pos, 66); - e.type := tBOOLEAN; + e._type := tBOOLEAN; IF e.obj = eCONST THEN ARITH.odd(e.value) ELSE @@ -1128,10 +1156,10 @@ BEGIN END ELSE IF isBoolean(e) THEN - IL.AddCmd0(IL.opORD) + IL._ord END END; - e.type := tINTEGER + e._type := tINTEGER |PROG.stBITS: PExpression(parser, e); @@ -1139,63 +1167,63 @@ BEGIN IF e.obj = eCONST THEN ARITH.bits(e.value) END; - e.type := tSET + e._type := tSET |PROG.sysADR: parser.designator(parser, e); IF isVar(e) THEN - n := PROG.Dim(e.type); - WHILE n > 0 DO + n := PROG.Dim(e._type); + WHILE n > 0 DO IL.drop; DEC(n) - END + END ELSIF e.obj = ePROC THEN IL.PushProc(e.ident.proc.label) ELSIF e.obj = eIMP THEN - IL.PushImpProc(e.ident.import) + IL.PushImpProc(e.ident._import) ELSE PARS.error(pos, 108) END; - e.type := tINTEGER + e._type := tINTEGER |PROG.sysSADR: PExpression(parser, e); PARS.check(isString(e), pos, 66); IL.StrAdr(String(e)); - e.type := tINTEGER; + e._type := tINTEGER; e.obj := eEXPR |PROG.sysWSADR: PExpression(parser, e); PARS.check(isStringW(e), pos, 66); IL.StrAdr(StringW(e)); - e.type := tINTEGER; + e._type := tINTEGER; e.obj := eEXPR |PROG.sysTYPEID: PExpression(parser, e); PARS.check(e.obj = eTYPE, pos, 68); - IF e.type.typ = PROG.tRECORD THEN - ASSERT(ARITH.setInt(e.value, e.type.num)) - ELSIF e.type.typ = PROG.tPOINTER THEN - ASSERT(ARITH.setInt(e.value, e.type.base.num)) + IF e._type.typ = PROG.tRECORD THEN + ASSERT(ARITH.setInt(e.value, e._type.num)) + ELSIF e._type.typ = PROG.tPOINTER THEN + ASSERT(ARITH.setInt(e.value, e._type.base.num)) ELSE PARS.error(pos, 52) END; e.obj := eCONST; - e.type := tINTEGER + e._type := tINTEGER |PROG.sysINF: - PARS.check(IL.inf(), pos, 41); + IL.AddCmd2(IL.opINF, pos.line, pos.col); e.obj := eEXPR; - e.type := tREAL + e._type := tREAL |PROG.sysSIZE: PExpression(parser, e); PARS.check(e.obj = eTYPE, pos, 68); - ASSERT(ARITH.setInt(e.value, e.type.size)); + ASSERT(ARITH.setInt(e.value, e._type.size)); e.obj := eCONST; - e.type := tINTEGER + e._type := tINTEGER END @@ -1215,7 +1243,7 @@ END stProc; PROCEDURE ActualParameters (parser: PARS.PARSER; VAR e: PARS.EXPR); VAR - proc: PROG.TYPE_; + proc: PROG._TYPE; param: LISTS.ITEM; e1: PARS.EXPR; pos: PARS.POSITION; @@ -1224,7 +1252,7 @@ BEGIN ASSERT(parser.sym = SCAN.lxLROUND); IF (e.obj IN {ePROC, eIMP}) OR isExpr(e) THEN - proc := e.type; + proc := e._type; PARS.check1(proc.typ = PROG.tPROCEDURE, parser, 86); PARS.Next(parser); @@ -1251,7 +1279,7 @@ BEGIN PARS.Next(parser); e.obj := eEXPR; - e.type := proc.base + e._type := proc.base ELSIF e.obj IN {eSTPROC, eSTFUNC, eSYSPROC, eSYSFUNC} THEN stProc(parser, e) @@ -1264,14 +1292,14 @@ END ActualParameters; PROCEDURE qualident (parser: PARS.PARSER; VAR e: PARS.EXPR); VAR - ident: PROG.IDENT; - import: BOOLEAN; - pos: PARS.POSITION; + ident: PROG.IDENT; + imp: BOOLEAN; + pos: PARS.POSITION; BEGIN PARS.checklex(parser, SCAN.lxIDENT); getpos(parser, pos); - import := FALSE; + imp := FALSE; ident := PROG.getIdent(parser.unit, parser.lex.ident, FALSE); PARS.check1(ident # NIL, parser, 48); IF ident.typ = PROG.idMODULE THEN @@ -1279,7 +1307,7 @@ BEGIN PARS.ExpectSym(parser, SCAN.lxIDENT); ident := PROG.getIdent(ident.unit, parser.lex.ident, FALSE); PARS.check1((ident # NIL) & ident.export, parser, 48); - import := TRUE + imp := TRUE END; PARS.Next(parser); @@ -1289,44 +1317,48 @@ BEGIN CASE ident.typ OF |PROG.idCONST: e.obj := eCONST; - e.type := ident.type; + e._type := ident._type; e.value := ident.value |PROG.idTYPE: - e.obj := eTYPE; - e.type := ident.type + e.obj := eTYPE; + e._type := ident._type |PROG.idVAR: - e.obj := eVAR; - e.type := ident.type; - e.readOnly := import + e.obj := eVAR; + e._type := ident._type; + e.readOnly := imp |PROG.idPROC: e.obj := ePROC; - e.type := ident.type + e._type := ident._type |PROG.idIMP: e.obj := eIMP; - e.type := ident.type + e._type := ident._type |PROG.idVPAR: - e.type := ident.type; - IF e.type.typ = PROG.tRECORD THEN + e._type := ident._type; + IF e._type.typ = PROG.tRECORD THEN e.obj := eVREC ELSE e.obj := eVPAR END |PROG.idPARAM: - e.obj := ePARAM; - e.type := ident.type; - e.readOnly := (e.type.typ IN {PROG.tRECORD, PROG.tARRAY}) + e.obj := ePARAM; + e._type := ident._type; + e.readOnly := (e._type.typ IN {PROG.tRECORD, PROG.tARRAY}) |PROG.idSTPROC: e.obj := eSTPROC; + e._type := ident._type; e.stproc := ident.stproc |PROG.idSTFUNC: e.obj := eSTFUNC; + e._type := ident._type; e.stproc := ident.stproc |PROG.idSYSPROC: e.obj := eSYSPROC; + e._type := ident._type; e.stproc := ident.stproc |PROG.idSYSFUNC: PARS.check(~parser.constexp, pos, 109); e.obj := eSYSFUNC; + e._type := ident._type; e.stproc := ident.stproc |PROG.idNONE: PARS.error(pos, 115) @@ -1345,12 +1377,12 @@ VAR BEGIN IF load THEN - IL.load(e.type.size) + IL.load(e._type.size) END; IF chkPTR IN Options.checking THEN label := IL.NewLabel(); - IL.AddJmpCmd(IL.opJNZ, label); + IL.AddJmpCmd(IL.opJNZ1, label); IL.OnError(pos.line, error); IL.SetLabel(label) END @@ -1373,7 +1405,7 @@ VAR offset, n: INTEGER; BEGIN offset := e.ident.offset; - n := PROG.Dim(e.type); + n := PROG.Dim(e._type); WHILE n >= 0 DO IL.AddCmd(IL.opVADR, offset); DEC(offset); @@ -1384,22 +1416,22 @@ VAR BEGIN IF e.obj = eVAR THEN - offset := PROG.getOffset(PARS.program, e.ident); + offset := PROG.getOffset(e.ident); IF e.ident.global THEN IL.AddCmd(IL.opGADR, offset) ELSE IL.AddCmd(IL.opLADR, -offset) END ELSIF e.obj = ePARAM THEN - IF (e.type.typ = PROG.tRECORD) OR ((e.type.typ = PROG.tARRAY) & (e.type.length > 0)) THEN + IF (e._type.typ = PROG.tRECORD) OR ((e._type.typ = PROG.tARRAY) & (e._type.length > 0)) THEN IL.AddCmd(IL.opVADR, e.ident.offset) - ELSIF PROG.isOpenArray(e.type) THEN + ELSIF PROG.isOpenArray(e._type) THEN OpenArray(e) ELSE IL.AddCmd(IL.opLADR, e.ident.offset) END ELSIF e.obj IN {eVPAR, eVREC} THEN - IF PROG.isOpenArray(e.type) THEN + IF PROG.isOpenArray(e._type) THEN OpenArray(e) ELSE IL.AddCmd(IL.opVADR, e.ident.offset) @@ -1411,7 +1443,7 @@ VAR PROCEDURE OpenIdx (parser: PARS.PARSER; pos: PARS.POSITION; e: PARS.EXPR); VAR label, offset, n, k: INTEGER; - type: PROG.TYPE_; + _type: PROG._TYPE; BEGIN @@ -1424,11 +1456,11 @@ VAR IL.AddCmd(IL.opCHKIDX2, -1) END; - type := PROG.OpenBase(e.type); - IF type.size # 1 THEN - IL.AddCmd(IL.opMULC, type.size) + _type := PROG.OpenBase(e._type); + IF _type.size # 1 THEN + IL.AddCmd(IL.opMULC, _type.size) END; - n := PROG.Dim(e.type) - 1; + n := PROG.Dim(e._type) - 1; k := n; WHILE n > 0 DO IL.AddCmd0(IL.opMUL); @@ -1458,23 +1490,23 @@ BEGIN WHILE parser.sym = SCAN.lxPOINT DO getpos(parser, pos); - PARS.check1(isExpr(e) & (e.type.typ IN {PROG.tRECORD, PROG.tPOINTER}), parser, 73); - IF e.type.typ = PROG.tPOINTER THEN + PARS.check1(isExpr(e) & (e._type.typ IN {PROG.tRECORD, PROG.tPOINTER}), parser, 73); + IF e._type.typ = PROG.tPOINTER THEN deref(pos, e, TRUE, errPTR) END; PARS.ExpectSym(parser, SCAN.lxIDENT); - IF e.type.typ = PROG.tPOINTER THEN - e.type := e.type.base; + IF e._type.typ = PROG.tPOINTER THEN + e._type := e._type.base; e.readOnly := FALSE END; - field := PROG.getField(e.type, parser.lex.ident, parser.unit); + field := PROG.getField(e._type, parser.lex.ident, parser.unit); PARS.check1(field # NIL, parser, 74); - e.type := field.type; + e._type := field._type; IF e.obj = eVREC THEN e.obj := eVPAR END; IF field.offset # 0 THEN - IL.AddCmd(IL.opADDR, field.offset) + IL.AddCmd(IL.opADDC, field.offset) END; PARS.Next(parser); e.ident := NIL @@ -1489,10 +1521,10 @@ BEGIN PARS.check(isInt(idx), pos, 76); IF idx.obj = eCONST THEN - IF e.type.length > 0 THEN - PARS.check(ARITH.range(idx.value, 0, e.type.length - 1), pos, 83); + IF e._type.length > 0 THEN + PARS.check(ARITH.range(idx.value, 0, e._type.length - 1), pos, 83); IF ARITH.Int(idx.value) > 0 THEN - IL.AddCmd(IL.opADDR, ARITH.Int(idx.value) * e.type.base.size) + IL.AddCmd(IL.opADDC, ARITH.Int(idx.value) * e._type.base.size) END ELSE PARS.check(ARITH.range(idx.value, 0, UTILS.target.maxInt), pos, 83); @@ -1500,12 +1532,12 @@ BEGIN OpenIdx(parser, pos, e) END ELSE - IF e.type.length > 0 THEN + IF e._type.length > 0 THEN IF chkIDX IN Options.checking THEN - CheckRange(e.type.length, pos.line, errIDX) + CheckRange(e._type.length, pos.line, errIDX) END; - IF e.type.base.size # 1 THEN - IL.AddCmd(IL.opMULC, e.type.base.size) + IF e._type.base.size # 1 THEN + IL.AddCmd(IL.opMULC, e._type.base.size) END; IL.AddCmd0(IL.opADD) ELSE @@ -1513,7 +1545,7 @@ BEGIN END END; - e.type := e.type.base + e._type := e._type.base UNTIL parser.sym # SCAN.lxCOMMA; @@ -1525,41 +1557,41 @@ BEGIN getpos(parser, pos); PARS.check1(isPtr(e), parser, 77); deref(pos, e, TRUE, errPTR); - e.type := e.type.base; + e._type := e._type.base; e.readOnly := FALSE; PARS.Next(parser); e.ident := NIL; e.obj := eVREC - ELSIF (parser.sym = SCAN.lxLROUND) & isExpr(e) & (e.type.typ IN {PROG.tRECORD, PROG.tPOINTER}) DO + ELSIF (parser.sym = SCAN.lxLROUND) & isExpr(e) & (e._type.typ IN {PROG.tRECORD, PROG.tPOINTER}) DO - IF e.type.typ = PROG.tRECORD THEN + IF e._type.typ = PROG.tRECORD THEN PARS.check1(e.obj = eVREC, parser, 78) END; NextPos(parser, pos); qualident(parser, t); PARS.check(t.obj = eTYPE, pos, 79); - IF e.type.typ = PROG.tRECORD THEN - PARS.check(t.type.typ = PROG.tRECORD, pos, 80); + IF e._type.typ = PROG.tRECORD THEN + PARS.check(t._type.typ = PROG.tRECORD, pos, 80); IF chkGUARD IN Options.checking THEN IF e.ident = NIL THEN - IL.TypeGuard(IL.opTYPEGD, t.type.num, pos.line, errGUARD) + IL.TypeGuard(IL.opTYPEGD, t._type.num, pos.line, errGUARD) ELSE IL.AddCmd(IL.opVADR, e.ident.offset - 1); - IL.TypeGuard(IL.opTYPEGR, t.type.num, pos.line, errGUARD) + IL.TypeGuard(IL.opTYPEGR, t._type.num, pos.line, errGUARD) END END; ELSE - PARS.check(t.type.typ = PROG.tPOINTER, pos, 81); + PARS.check(t._type.typ = PROG.tPOINTER, pos, 81); IF chkGUARD IN Options.checking THEN - IL.TypeGuard(IL.opTYPEGP, t.type.base.num, pos.line, errGUARD) + IL.TypeGuard(IL.opTYPEGP, t._type.base.num, pos.line, errGUARD) END END; - PARS.check(PROG.isBaseOf(e.type, t.type), pos, 82); + PARS.check(PROG.isBaseOf(e._type, t._type), pos, 82); - e.type := t.type; + e._type := t._type; PARS.checklex(parser, SCAN.lxRROUND); PARS.Next(parser) @@ -1569,7 +1601,7 @@ BEGIN END designator; -PROCEDURE ProcCall (e: PARS.EXPR; procType: PROG.TYPE_; isfloat: BOOLEAN; VAR fregs: INTEGER; parser: PARS.PARSER; pos: PARS.POSITION; CallStat: BOOLEAN); +PROCEDURE ProcCall (e: PARS.EXPR; procType: PROG._TYPE; isfloat: BOOLEAN; parser: PARS.PARSER; pos: PARS.POSITION; CallStat: BOOLEAN); VAR cconv, parSize, @@ -1594,7 +1626,7 @@ BEGIN fparSize := 0 END; IL.setlast(begcall); - fregs := IL.precall(isfloat); + IL.AddCmd(IL.opPRECALL, ORD(isfloat)); IF cconv IN {PROG._ccall16, PROG.ccall16} THEN IL.AddCmd(IL.opALIGN16, parSize) @@ -1606,7 +1638,7 @@ BEGIN IL.setlast(endcall.prev(IL.COMMAND)); IF e.obj = eIMP THEN - IL.CallImp(e.ident.import, callconv, fparSize) + IL.CallImp(e.ident._import, callconv, fparSize) ELSIF e.obj = ePROC THEN IL.Call(e.ident.proc.label, callconv, fparSize) ELSIF isExpr(e) THEN @@ -1627,11 +1659,14 @@ BEGIN IL.AddCmd(IL.opCLEANUP, parSize) END; - IF ~CallStat THEN + IF CallStat THEN + IL.AddCmd0(IL.opRES); + IL.drop + ELSE IF isfloat THEN - PARS.check(IL.resf(fregs), pos, 41) + IL.AddCmd2(IL.opRESF, pos.line, pos.col) ELSE - IL.res(fregs) + IL.AddCmd0(IL.opRES) END END END ProcCall; @@ -1640,12 +1675,9 @@ END ProcCall; PROCEDURE expression (parser: PARS.PARSER; VAR e: PARS.EXPR); VAR pos, pos0, pos1: PARS.POSITION; - - op: INTEGER; - e1: PARS.EXPR; - constant: BOOLEAN; - operator: ARITH.RELATION; - error: INTEGER; + e1: PARS.EXPR; + op, cmp, error: INTEGER; + constant, eq: BOOLEAN; PROCEDURE relation (sym: INTEGER): BOOLEAN; @@ -1701,7 +1733,7 @@ VAR END END; - e.type := tSET; + e._type := tSET; IF (e1.obj = eCONST) & (e2.obj = eCONST) THEN ARITH.constrSet(e.value, e1.value, e2.value); @@ -1732,7 +1764,7 @@ VAR ASSERT(parser.sym = SCAN.lxLCURLY); e.obj := eCONST; - e.type := tSET; + e._type := tSET; ARITH.emptySet(e.value); PARS.Next(parser); @@ -1752,9 +1784,9 @@ VAR ARITH.opSet(e.value, e1.value, "+") ELSE IF e.obj = eCONST THEN - IL.AddCmd(IL.opADDSL, ARITH.Int(e.value)) + IL.AddCmd(IL.opADDSC, ARITH.Int(e.value)) ELSIF e1.obj = eCONST THEN - IL.AddCmd(IL.opADDSR, ARITH.Int(e1.value)) + IL.AddCmd(IL.opADDSC, ARITH.Int(e1.value)) ELSE IL.AddCmd0(IL.opADDS) END; @@ -1773,16 +1805,15 @@ VAR pos: PARS.POSITION; e1: PARS.EXPR; isfloat: BOOLEAN; - fregs: INTEGER; PROCEDURE LoadVar (e: PARS.EXPR; parser: PARS.PARSER; pos: PARS.POSITION); BEGIN - IF ~(e.type.typ IN {PROG.tRECORD, PROG.tARRAY}) THEN - IF e.type = tREAL THEN - PARS.check(IL.loadf(), pos, 41) + IF ~(e._type.typ IN {PROG.tRECORD, PROG.tARRAY}) THEN + IF e._type = tREAL THEN + IL.AddCmd2(IL.opLOADF, pos.line, pos.col) ELSE - IL.load(e.type.size) + IL.load(e._type.size) END END END LoadVar; @@ -1794,18 +1825,18 @@ VAR IF (sym = SCAN.lxINTEGER) OR (sym = SCAN.lxHEX) OR (sym = SCAN.lxFLOAT) OR (sym = SCAN.lxCHAR) OR (sym = SCAN.lxSTRING) THEN e.obj := eCONST; e.value := parser.lex.value; - e.type := PROG.getType(PARS.program, e.value.typ); + e._type := PROG.getType(e.value.typ); PARS.Next(parser) ELSIF sym = SCAN.lxNIL THEN e.obj := eCONST; - e.type := PARS.program.stTypes.tNIL; + e._type := PROG.program.stTypes.tNIL; PARS.Next(parser) ELSIF (sym = SCAN.lxTRUE) OR (sym = SCAN.lxFALSE) THEN e.obj := eCONST; ARITH.setbool(e.value, sym = SCAN.lxTRUE); - e.type := tBOOLEAN; + e._type := tBOOLEAN; PARS.Next(parser) ELSIF sym = SCAN.lxLCURLY THEN @@ -1823,12 +1854,12 @@ VAR IF parser.sym = SCAN.lxLROUND THEN e1 := e; ActualParameters(parser, e); - PARS.check(e.type # NIL, pos, 59); - isfloat := e.type = tREAL; + PARS.check(e._type # NIL, pos, 59); + isfloat := e._type = tREAL; IF e1.obj IN {ePROC, eIMP} THEN - ProcCall(e1, e1.ident.type, isfloat, fregs, parser, pos, FALSE) + ProcCall(e1, e1.ident._type, isfloat, parser, pos, FALSE) ELSIF isExpr(e1) THEN - ProcCall(e1, e1.type, isfloat, fregs, parser, pos, FALSE) + ProcCall(e1, e1._type, isfloat, parser, pos, FALSE) END END; IL.popBegEnd(begcall, endcall) @@ -1884,9 +1915,7 @@ VAR IF e.obj = eCONST THEN IL.Const(ORD(ARITH.getBool(e.value))) END; - IL.AddCmd0(IL.opACC); - IL.AddJmpCmd(IL.opJZ, label); - IL.drop + IL.AndOrOpt(label) END END; @@ -1914,11 +1943,11 @@ VAR END ELSIF isReal(e) THEN IF e.obj = eCONST THEN - IL.Float(ARITH.Float(e.value)) + Float(parser, e) ELSIF e1.obj = eCONST THEN - IL.Float(ARITH.Float(e1.value)) + Float(parser, e1) END; - IL.fbinop(IL.opMULF) + IL.AddCmd0(IL.opMULF) ELSIF isSet(e) THEN IF e.obj = eCONST THEN IL.AddCmd(IL.opMULSC, ARITH.Int(e.value)) @@ -1946,13 +1975,13 @@ VAR ELSE IF isReal(e) THEN IF e.obj = eCONST THEN - IL.Float(ARITH.Float(e.value)); - IL.fbinop(IL.opDIVFI) + Float(parser, e); + IL.AddCmd0(IL.opDIVFI) ELSIF e1.obj = eCONST THEN - IL.Float(ARITH.Float(e1.value)); - IL.fbinop(IL.opDIVF) + Float(parser, e1); + IL.AddCmd0(IL.opDIVF) ELSE - IL.fbinop(IL.opDIVF) + IL.AddCmd0(IL.opDIVF) END ELSIF isSet(e) THEN IF e.obj = eCONST THEN @@ -2007,15 +2036,24 @@ VAR e.obj := eEXPR; IF e1.obj = eCONST THEN IL.Const(ORD(ARITH.getBool(e1.value))) - END; - IL.AddCmd0(IL.opACC) + END END END END; IF label # -1 THEN - IL.SetLabel(label) + label1 := IL.NewLabel(); + IL.AddJmpCmd(IL.opJNZ, label1); + IL.SetLabel(label); + IL.Const(0); + IL.drop; + label := IL.NewLabel(); + IL.AddJmpCmd(IL.opJMP, label); + IL.SetLabel(label1); + IL.Const(1); + IL.SetLabel(label); + IL.AddCmd0(IL.opAND) END END term; @@ -2025,10 +2063,11 @@ VAR pos: PARS.POSITION; op: INTEGER; e1: PARS.EXPR; + s, s1: SCAN.LEXSTR; plus, minus: BOOLEAN; - label: INTEGER; + label, label1: INTEGER; BEGIN plus := parser.sym = SCAN.lxPLUS; @@ -2066,7 +2105,7 @@ VAR WHILE AddOperator(parser.sym) DO - op := parser.sym; + op := parser.sym; getpos(parser, pos); PARS.Next(parser); @@ -2081,9 +2120,8 @@ VAR IF e.obj = eCONST THEN IL.Const(ORD(ARITH.getBool(e.value))) END; - IL.AddCmd0(IL.opACC); - IL.AddJmpCmd(IL.opJNZ, label); - IL.drop + IL.not; + IL.AndOrOpt(label) END END; @@ -2093,47 +2131,69 @@ VAR CASE op OF |SCAN.lxPLUS, SCAN.lxMINUS: - IF op = SCAN.lxPLUS THEN - op := ORD("+") - ELSE + minus := op = SCAN.lxMINUS; + IF minus THEN op := ORD("-") + ELSE + op := ORD("+") END; - PARS.check(isInt(e) & isInt(e1) OR isReal(e) & isReal(e1) OR isSet(e) & isSet(e1), pos, 37); + PARS.check(isInt(e) & isInt(e1) OR isReal(e) & isReal(e1) OR isSet(e) & isSet(e1) OR isString(e) & isString(e1) & ~minus, pos, 37); IF (e.obj = eCONST) & (e1.obj = eCONST) THEN - CASE e.value.typ OF - |ARITH.tINTEGER: PARS.check(ARITH.opInt(e.value, e1.value, CHR(op)), pos, 39) - |ARITH.tREAL: PARS.check(ARITH.opFloat(e.value, e1.value, CHR(op)), pos, 40) - |ARITH.tSET: ARITH.opSet(e.value, e1.value, CHR(op)) + CASE e.value.typ OF + |ARITH.tINTEGER: + PARS.check(ARITH.opInt(e.value, e1.value, CHR(op)), pos, 39) + + |ARITH.tREAL: + PARS.check(ARITH.opFloat(e.value, e1.value, CHR(op)), pos, 40) + + |ARITH.tSET: + ARITH.opSet(e.value, e1.value, CHR(op)) + + |ARITH.tCHAR, ARITH.tSTRING: + IF e.value.typ = ARITH.tCHAR THEN + ARITH.charToStr(e.value, s) + ELSE + s := e.value.string(SCAN.IDENT).s + END; + IF e1.value.typ = ARITH.tCHAR THEN + ARITH.charToStr(e1.value, s1) + ELSE + s1 := e1.value.string(SCAN.IDENT).s + END; + PARS.check(ARITH.concat(s, s1), pos, 5); + e.value.string := SCAN.enterid(s); + e.value.typ := ARITH.tSTRING; + e._type := PROG.program.stTypes.tSTRING END ELSE IF isInt(e) THEN IF e.obj = eCONST THEN - IL.AddCmd(IL.opADDL + ORD(op = ORD("-")), ARITH.Int(e.value)) + IL.AddCmd(IL.opADDC - ORD(minus), ARITH.Int(e.value)) ELSIF e1.obj = eCONST THEN - IL.AddCmd(IL.opADDR + ORD(op = ORD("-")), ARITH.Int(e1.value)) + IL.AddCmd(IL.opADDC + ORD(minus), ARITH.Int(e1.value)) ELSE - IL.AddCmd0(IL.opADD + ORD(op = ORD("-"))) + IL.AddCmd0(IL.opADD + ORD(minus)) END ELSIF isReal(e) THEN IF e.obj = eCONST THEN - IL.Float(ARITH.Float(e.value)); - IL.fbinop(IL.opADDFI + ORD(op = ORD("-"))) + Float(parser, e); + IL.AddCmd0(IL.opADDF - ORD(minus)) ELSIF e1.obj = eCONST THEN - IL.Float(ARITH.Float(e1.value)); - IL.fbinop(IL.opADDF + ORD(op = ORD("-"))) + Float(parser, e1); + IL.AddCmd0(IL.opADDF + ORD(minus)) ELSE - IL.fbinop(IL.opADDF + ORD(op = ORD("-"))) + IL.AddCmd0(IL.opADDF + ORD(minus)) END ELSIF isSet(e) THEN IF e.obj = eCONST THEN - IL.AddCmd(IL.opADDSL + ORD(op = ORD("-")), ARITH.Int(e.value)) + IL.AddCmd(IL.opADDSC - ORD(minus), ARITH.Int(e.value)) ELSIF e1.obj = eCONST THEN - IL.AddCmd(IL.opADDSR + ORD(op = ORD("-")), ARITH.Int(e1.value)) + IL.AddCmd(IL.opADDSC + ORD(minus), ARITH.Int(e1.value)) ELSE - IL.AddCmd0(IL.opADDS + ORD(op = ORD("-"))) + IL.AddCmd0(IL.opADDS + ORD(minus)) END END; e.obj := eEXPR @@ -2148,15 +2208,24 @@ VAR e.obj := eEXPR; IF e1.obj = eCONST THEN IL.Const(ORD(ARITH.getBool(e1.value))) - END; - IL.AddCmd0(IL.opACC) + END END END END; IF label # -1 THEN - IL.SetLabel(label) + label1 := IL.NewLabel(); + IL.AddJmpCmd(IL.opJZ, label1); + IL.SetLabel(label); + IL.Const(1); + IL.drop; + label := IL.NewLabel(); + IL.AddJmpCmd(IL.opJMP, label); + IL.SetLabel(label1); + IL.Const(0); + IL.SetLabel(label); + IL.AddCmd0(IL.opOR) END END SimpleExpression; @@ -2168,12 +2237,14 @@ VAR BEGIN CASE op OF - |SCAN.lxEQ: res := 0 - |SCAN.lxNE: res := 1 - |SCAN.lxLT: res := 2 - |SCAN.lxLE: res := 3 - |SCAN.lxGT: res := 4 - |SCAN.lxGE: res := 5 + |SCAN.lxEQ: res := ARITH.opEQ + |SCAN.lxNE: res := ARITH.opNE + |SCAN.lxLT: res := ARITH.opLT + |SCAN.lxLE: res := ARITH.opLE + |SCAN.lxGT: res := ARITH.opGT + |SCAN.lxGE: res := ARITH.opGE + |SCAN.lxIN: res := ARITH.opIN + |SCAN.lxIS: res := ARITH.opIS END RETURN res @@ -2186,12 +2257,14 @@ VAR BEGIN CASE op OF - |SCAN.lxEQ: res := 0 - |SCAN.lxNE: res := 1 - |SCAN.lxLT: res := 4 - |SCAN.lxLE: res := 5 - |SCAN.lxGT: res := 2 - |SCAN.lxGE: res := 3 + |SCAN.lxEQ: res := ARITH.opEQ + |SCAN.lxNE: res := ARITH.opNE + |SCAN.lxLT: res := ARITH.opGT + |SCAN.lxLE: res := ARITH.opGE + |SCAN.lxGT: res := ARITH.opLT + |SCAN.lxGE: res := ARITH.opLE + |SCAN.lxIN: res := ARITH.opIN + |SCAN.lxIS: res := ARITH.opIS END RETURN res @@ -2211,21 +2284,18 @@ VAR PROCEDURE strcmp (VAR e, e1: PARS.EXPR; op: INTEGER): BOOLEAN; VAR res: BOOLEAN; + cmp: INTEGER; BEGIN res := TRUE; + cmp := cmpcode(op); IF isString(e) & isCharArray(e1) THEN IL.StrAdr(String(e)); IL.Const(strlen(e) + 1); IL.AddCmd0(IL.opEQS + invcmpcode(op)) - ELSIF isString(e) & isCharArrayW(e1) THEN - IL.StrAdr(StringW(e)); - IL.Const(utf8strlen(e) + 1); - IL.AddCmd0(IL.opEQSW + invcmpcode(op)) - - ELSIF isStringW(e) & isCharArrayW(e1) THEN + ELSIF (isString(e) OR isStringW(e)) & isCharArrayW(e1) THEN IL.StrAdr(StringW(e)); IL.Const(utf8strlen(e) + 1); IL.AddCmd0(IL.opEQSW + invcmpcode(op)) @@ -2233,23 +2303,18 @@ VAR ELSIF isCharArray(e) & isString(e1) THEN IL.StrAdr(String(e1)); IL.Const(strlen(e1) + 1); - IL.AddCmd0(IL.opEQS + cmpcode(op)) + IL.AddCmd0(IL.opEQS + cmp) - ELSIF isCharArrayW(e) & isString(e1) THEN + ELSIF isCharArrayW(e) & (isString(e1) OR isStringW(e1)) THEN IL.StrAdr(StringW(e1)); IL.Const(utf8strlen(e1) + 1); - IL.AddCmd0(IL.opEQSW + cmpcode(op)) - - ELSIF isCharArrayW(e) & isStringW(e1) THEN - IL.StrAdr(StringW(e1)); - IL.Const(utf8strlen(e1) + 1); - IL.AddCmd0(IL.opEQSW + cmpcode(op)) + IL.AddCmd0(IL.opEQSW + cmp) ELSIF isCharArrayW(e) & isCharArrayW(e1) THEN - IL.AddCmd0(IL.opEQSW + cmpcode(op)) + IL.AddCmd0(IL.opEQSW + cmp) ELSIF isCharArray(e) & isCharArray(e1) THEN - IL.AddCmd0(IL.opEQS + cmpcode(op)) + IL.AddCmd0(IL.opEQS + cmp) ELSIF isString(e) & isString(e1) THEN PARS.strcmp(e.value, e1.value, op) @@ -2267,71 +2332,60 @@ BEGIN getpos(parser, pos0); SimpleExpression(parser, e); IF relation(parser.sym) THEN - IF (isCharArray(e) OR isCharArrayW(e)) & (e.type.length # 0) THEN - IL.Const(e.type.length) + IF (isCharArray(e) OR isCharArrayW(e)) & (e._type.length # 0) THEN + IL.Const(e._type.length) END; - op := parser.sym; + op := parser.sym; getpos(parser, pos); PARS.Next(parser); getpos(parser, pos1); SimpleExpression(parser, e1); - IF (isCharArray(e1) OR isCharArrayW(e1)) & (e1.type.length # 0) THEN - IL.Const(e1.type.length) + IF (isCharArray(e1) OR isCharArrayW(e1)) & (e1._type.length # 0) THEN + IL.Const(e1._type.length) END; constant := (e.obj = eCONST) & (e1.obj = eCONST); - - CASE op OF - |SCAN.lxEQ: operator := "=" - |SCAN.lxNE: operator := "#" - |SCAN.lxLT: operator := "<" - |SCAN.lxLE: operator := "<=" - |SCAN.lxGT: operator := ">" - |SCAN.lxGE: operator := ">=" - |SCAN.lxIN: operator := "IN" - |SCAN.lxIS: operator := "" - END; - error := 0; + cmp := cmpcode(op); CASE op OF |SCAN.lxEQ, SCAN.lxNE: - + eq := op = SCAN.lxEQ; IF isInt(e) & isInt(e1) OR isSet(e) & isSet(e1) OR isChar(e) & isChar(e1) OR isCharW(e) & isCharW(e1) OR isCharW(e) & isChar(e1) & (e1.obj = eCONST) OR isCharW(e1) & isChar(e) & (e.obj = eCONST) OR isCharW(e1) & (e1.obj = eCONST) & isChar(e) & (e.obj = eCONST) OR isCharW(e) & (e.obj = eCONST) & isChar(e1) & (e1.obj = eCONST) OR - isPtr(e) & isPtr(e1) & (PROG.isBaseOf(e.type, e1.type) OR PROG.isBaseOf(e1.type, e.type)) THEN + isPtr(e) & isPtr(e1) & (PROG.isBaseOf(e._type, e1._type) OR PROG.isBaseOf(e1._type, e._type)) THEN IF constant THEN - ARITH.relation(e.value, e1.value, operator, error) + ARITH.relation(e.value, e1.value, cmp, error) ELSE IF e.obj = eCONST THEN - IL.AddCmd(IL.opEQC + cmpcode(op), ARITH.Int(e.value)) + IL.AddCmd(IL.opEQC + cmp, ARITH.Int(e.value)) ELSIF e1.obj = eCONST THEN - IL.AddCmd(IL.opEQC + cmpcode(op), ARITH.Int(e1.value)) + IL.AddCmd(IL.opEQC + cmp, ARITH.Int(e1.value)) ELSE - IL.AddCmd0(IL.opEQ + cmpcode(op)) + IL.AddCmd0(IL.opEQ + cmp) END END ELSIF isStringW1(e) & isCharW(e1) THEN - IL.AddCmd(IL.opEQC + cmpcode(op), StrToWChar(e.value.string(SCAN.IDENT).s)) + IL.AddCmd(IL.opEQC + cmp, StrToWChar(e.value.string(SCAN.IDENT).s)) ELSIF isStringW1(e1) & isCharW(e) THEN - IL.AddCmd(IL.opEQC + cmpcode(op), StrToWChar(e1.value.string(SCAN.IDENT).s)) + IL.AddCmd(IL.opEQC + cmp, StrToWChar(e1.value.string(SCAN.IDENT).s)) ELSIF isBoolean(e) & isBoolean(e1) THEN IF constant THEN - ARITH.relation(e.value, e1.value, operator, error) + ARITH.relation(e.value, e1.value, cmp, error) ELSE IF e.obj = eCONST THEN - BoolCmp(op = SCAN.lxEQ, ARITH.Int(e.value) # 0) + BoolCmp(eq, ARITH.Int(e.value) # 0) ELSIF e1.obj = eCONST THEN - BoolCmp(op = SCAN.lxEQ, ARITH.Int(e1.value) # 0) + BoolCmp(eq, ARITH.Int(e1.value) # 0) ELSE - IF op = SCAN.lxEQ THEN + IF eq THEN IL.AddCmd0(IL.opEQB) ELSE IL.AddCmd0(IL.opNEB) @@ -2341,14 +2395,14 @@ BEGIN ELSIF isReal(e) & isReal(e1) THEN IF constant THEN - ARITH.relation(e.value, e1.value, operator, error) + ARITH.relation(e.value, e1.value, cmp, error) ELSE IF e.obj = eCONST THEN - IL.Float(ARITH.Float(e.value)) + Float(parser, e) ELSIF e1.obj = eCONST THEN - IL.Float(ARITH.Float(e1.value)) + Float(parser, e1) END; - IL.fcmp(IL.opEQF + cmpcode(op)) + IL.AddCmd0(IL.opEQF + cmp) END ELSIF (isStringW(e) OR isCharArrayX(e)) & (isStringW(e1) OR isCharArrayX(e1)) THEN @@ -2357,16 +2411,16 @@ BEGIN END ELSIF isPtr(e) & isNil(e1) OR isNil(e) & isPtr(e1) THEN - IL.AddCmd0(IL.opEQC + cmpcode(op)) + IL.AddCmd0(IL.opEQC + cmp) ELSIF isProc(e) & isNil(e1) THEN IF e.obj IN {ePROC, eIMP} THEN PARS.check(e.ident.global, pos0, 85); constant := TRUE; e.obj := eCONST; - ARITH.setbool(e.value, op = SCAN.lxNE) + ARITH.setbool(e.value, ~eq) ELSE - IL.AddCmd0(IL.opEQC + cmpcode(op)) + IL.AddCmd0(IL.opEQC + cmp) END ELSIF isNil(e) & isProc(e1) THEN @@ -2374,12 +2428,12 @@ BEGIN PARS.check(e1.ident.global, pos1, 85); constant := TRUE; e.obj := eCONST; - ARITH.setbool(e.value, op = SCAN.lxNE) + ARITH.setbool(e.value, ~eq) ELSE - IL.AddCmd0(IL.opEQC + cmpcode(op)) + IL.AddCmd0(IL.opEQC + cmp) END - ELSIF isProc(e) & isProc(e1) & PROG.isTypeEq(e.type, e1.type) THEN + ELSIF isProc(e) & isProc(e1) & PROG.isTypeEq(e._type, e1._type) THEN IF e.obj = ePROC THEN PARS.check(e.ident.global, pos0, 85) END; @@ -2389,27 +2443,27 @@ BEGIN IF (e.obj IN {ePROC, eIMP}) & (e1.obj IN {ePROC, eIMP}) THEN constant := TRUE; e.obj := eCONST; - IF op = SCAN.lxEQ THEN + IF eq THEN ARITH.setbool(e.value, e.ident = e1.ident) ELSE ARITH.setbool(e.value, e.ident # e1.ident) END ELSIF e.obj = ePROC THEN - IL.ProcCmp(e.ident.proc.label, op = SCAN.lxEQ) + IL.ProcCmp(e.ident.proc.label, eq) ELSIF e1.obj = ePROC THEN - IL.ProcCmp(e1.ident.proc.label, op = SCAN.lxEQ) + IL.ProcCmp(e1.ident.proc.label, eq) ELSIF e.obj = eIMP THEN - IL.ProcImpCmp(e.ident.import, op = SCAN.lxEQ) + IL.ProcImpCmp(e.ident._import, eq) ELSIF e1.obj = eIMP THEN - IL.ProcImpCmp(e1.ident.import, op = SCAN.lxEQ) + IL.ProcImpCmp(e1.ident._import, eq) ELSE - IL.AddCmd0(IL.opEQ + cmpcode(op)) + IL.AddCmd0(IL.opEQ + cmp) END ELSIF isNil(e) & isNil(e1) THEN constant := TRUE; e.obj := eCONST; - ARITH.setbool(e.value, op = SCAN.lxEQ) + ARITH.setbool(e.value, eq) ELSE PARS.error(pos, 37) @@ -2422,14 +2476,14 @@ BEGIN isCharW(e) & (e.obj = eCONST) & isChar(e1) & (e1.obj = eCONST) THEN IF constant THEN - ARITH.relation(e.value, e1.value, operator, error) + ARITH.relation(e.value, e1.value, cmp, error) ELSE IF e.obj = eCONST THEN IL.AddCmd(IL.opEQC + invcmpcode(op), ARITH.Int(e.value)) ELSIF e1.obj = eCONST THEN - IL.AddCmd(IL.opEQC + cmpcode(op), ARITH.Int(e1.value)) + IL.AddCmd(IL.opEQC + cmp, ARITH.Int(e1.value)) ELSE - IL.AddCmd0(IL.opEQ + cmpcode(op)) + IL.AddCmd0(IL.opEQ + cmp) END END @@ -2437,20 +2491,20 @@ BEGIN IL.AddCmd(IL.opEQC + invcmpcode(op), StrToWChar(e.value.string(SCAN.IDENT).s)) ELSIF isStringW1(e1) & isCharW(e) THEN - IL.AddCmd(IL.opEQC + cmpcode(op), StrToWChar(e1.value.string(SCAN.IDENT).s)) + IL.AddCmd(IL.opEQC + cmp, StrToWChar(e1.value.string(SCAN.IDENT).s)) ELSIF isReal(e) & isReal(e1) THEN IF constant THEN - ARITH.relation(e.value, e1.value, operator, error) + ARITH.relation(e.value, e1.value, cmp, error) ELSE IF e.obj = eCONST THEN - IL.Float(ARITH.Float(e.value)); - IL.fcmp(IL.opEQF + invcmpcode(op)) + Float(parser, e); + IL.AddCmd0(IL.opEQF + invcmpcode(op)) ELSIF e1.obj = eCONST THEN - IL.Float(ARITH.Float(e1.value)); - IL.fcmp(IL.opEQF + cmpcode(op)) + Float(parser, e1); + IL.AddCmd0(IL.opEQF + cmp) ELSE - IL.fcmp(IL.opEQF + cmpcode(op)) + IL.AddCmd0(IL.opEQF + cmp) END END @@ -2469,7 +2523,7 @@ BEGIN PARS.check(ARITH.range(e.value, 0, UTILS.target.maxSet), pos0, 56) END; IF constant THEN - ARITH.relation(e.value, e1.value, operator, error) + ARITH.relation(e.value, e1.value, ARITH.opIN, error) ELSE IF e.obj = eCONST THEN IL.AddCmd(IL.opINL, ARITH.Int(e.value)) @@ -2486,25 +2540,25 @@ BEGIN IF isRec(e) THEN PARS.check(e.obj = eVREC, pos0, 78); - PARS.check(e1.type.typ = PROG.tRECORD, pos1, 80); + PARS.check(e1._type.typ = PROG.tRECORD, pos1, 80); IF e.ident = NIL THEN - IL.TypeCheck(e1.type.num) + IL.TypeCheck(e1._type.num) ELSE IL.AddCmd(IL.opVADR, e.ident.offset - 1); - IL.TypeCheckRec(e1.type.num) + IL.TypeCheckRec(e1._type.num) END ELSE - PARS.check(e1.type.typ = PROG.tPOINTER, pos1, 81); - IL.TypeCheck(e1.type.base.num) + PARS.check(e1._type.typ = PROG.tPOINTER, pos1, 81); + IL.TypeCheck(e1._type.base.num) END; - PARS.check(PROG.isBaseOf(e.type, e1.type), pos1, 82) + PARS.check(PROG.isBaseOf(e._type, e1._type), pos1, 82) END; ASSERT(error = 0); - e.type := tBOOLEAN; + e._type := tBOOLEAN; IF ~constant THEN e.obj := eEXPR @@ -2520,7 +2574,6 @@ VAR pos: PARS.POSITION; line: INTEGER; call: BOOLEAN; - fregs: INTEGER; BEGIN getpos(parser, pos); @@ -2541,7 +2594,7 @@ BEGIN IL.setlast(endcall.prev(IL.COMMAND)); - PARS.check(assign(e1, e.type, line), pos, 91); + PARS.check(assign(parser, e1, e._type, line), pos, 91); IF e1.obj = ePROC THEN PARS.check(e1.ident.global, pos, 85) END; @@ -2551,7 +2604,7 @@ BEGIN ELSIF parser.sym = SCAN.lxLROUND THEN e1 := e; ActualParameters(parser, e1); - PARS.check((e1.type = NIL) OR ODD(e.type.call), pos, 92); + PARS.check((e1._type = NIL) OR ODD(e._type.call), pos, 92); call := TRUE ELSE IF e.obj IN {eSYSPROC, eSTPROC} THEN @@ -2559,17 +2612,17 @@ BEGIN call := FALSE ELSE PARS.check(isProc(e), pos, 86); - PARS.check((e.type.base = NIL) OR ODD(e.type.call), pos, 92); - PARS.check1(e.type.params.first = NIL, parser, 64); + PARS.check((e._type.base = NIL) OR ODD(e._type.call), pos, 92); + PARS.check1(e._type.params.first = NIL, parser, 64); call := TRUE END END; IF call THEN IF e.obj IN {ePROC, eIMP} THEN - ProcCall(e, e.ident.type, FALSE, fregs, parser, pos, TRUE) + ProcCall(e, e.ident._type, FALSE, parser, pos, TRUE) ELSIF isExpr(e) THEN - ProcCall(e, e.type, FALSE, fregs, parser, pos, TRUE) + ProcCall(e, e._type, FALSE, parser, pos, TRUE) END END; @@ -2577,7 +2630,7 @@ BEGIN END ElementaryStatement; -PROCEDURE IfStatement (parser: PARS.PARSER; if: BOOLEAN); +PROCEDURE IfStatement (parser: PARS.PARSER; _if: BOOLEAN); VAR e: PARS.EXPR; pos: PARS.POSITION; @@ -2587,7 +2640,7 @@ VAR BEGIN L := IL.NewLabel(); - IF ~if THEN + IF ~_if THEN IL.AddCmd0(IL.opLOOP); IL.SetLabel(L) END; @@ -2605,10 +2658,10 @@ BEGIN IL.AddJmpCmd(IL.opJMP, label) END ELSE - IL.AddJmpCmd(IL.opJNE, label) + IL.AndOrOpt(label) END; - IF if THEN + IF _if THEN PARS.checklex(parser, SCAN.lxTHEN) ELSE PARS.checklex(parser, SCAN.lxDO) @@ -2617,25 +2670,25 @@ BEGIN PARS.Next(parser); parser.StatSeq(parser); - IL.AddJmpCmd(IL.opJMP, L); + IF ~_if OR (parser.sym # SCAN.lxEND) THEN + IL.AddJmpCmd(IL.opJMP, L) + END; IL.SetLabel(label) UNTIL parser.sym # SCAN.lxELSIF; - IF if THEN + IF _if THEN IF parser.sym = SCAN.lxELSE THEN PARS.Next(parser); parser.StatSeq(parser) END; IL.SetLabel(L) + ELSE + IL.AddCmd0(IL.opENDLOOP) END; PARS.checklex(parser, SCAN.lxEND); - IF ~if THEN - IL.AddCmd0(IL.opENDLOOP) - END; - PARS.Next(parser) END IfStatement; @@ -2645,12 +2698,14 @@ VAR e: PARS.EXPR; pos: PARS.POSITION; label: INTEGER; + L: IL.COMMAND; BEGIN IL.AddCmd0(IL.opLOOP); label := IL.NewLabel(); IL.SetLabel(label); + L := IL.getlast(); PARS.Next(parser); parser.StatSeq(parser); @@ -2664,7 +2719,8 @@ BEGIN IL.AddJmpCmd(IL.opJMP, label) END ELSE - IL.AddJmpCmd(IL.opJNE, label) + IL.AndOrOpt(label); + L.param1 := label END; IL.AddCmd0(IL.opENDLOOP) @@ -2724,7 +2780,7 @@ VAR pos: PARS.POSITION; - PROCEDURE Label (parser: PARS.PARSER; caseExpr: PARS.EXPR; VAR type: PROG.TYPE_): INTEGER; + PROCEDURE Label (parser: PARS.PARSER; caseExpr: PARS.EXPR; VAR _type: PROG._TYPE): INTEGER; VAR a: INTEGER; label: PARS.EXPR; @@ -2733,7 +2789,7 @@ VAR BEGIN getpos(parser, pos); - type := NIL; + _type := NIL; IF isChar(caseExpr) THEN PARS.ConstExpression(parser, value); @@ -2754,25 +2810,25 @@ VAR ELSIF isRecPtr(caseExpr) THEN qualident(parser, label); PARS.check(label.obj = eTYPE, pos, 79); - PARS.check(PROG.isBaseOf(caseExpr.type, label.type), pos, 99); + PARS.check(PROG.isBaseOf(caseExpr._type, label._type), pos, 99); IF isRec(caseExpr) THEN - a := label.type.num + a := label._type.num ELSE - a := label.type.base.num + a := label._type.base.num END; - type := label.type + _type := label._type END RETURN a END Label; - PROCEDURE CheckType (node: AVL.NODE; type: PROG.TYPE_; parser: PARS.PARSER; pos: PARS.POSITION); + PROCEDURE CheckType (node: AVL.NODE; _type: PROG._TYPE; parser: PARS.PARSER; pos: PARS.POSITION); BEGIN IF node # NIL THEN - PARS.check(~(PROG.isBaseOf(node.data(CASE_LABEL).type, type) OR PROG.isBaseOf(type, node.data(CASE_LABEL).type)), pos, 100); - CheckType(node.left, type, parser, pos); - CheckType(node.right, type, parser, pos) + PARS.check(~(PROG.isBaseOf(node.data(CASE_LABEL)._type, _type) OR PROG.isBaseOf(_type, node.data(CASE_LABEL)._type)), pos, 100); + CheckType(node.left, _type, parser, pos); + CheckType(node.right, _type, parser, pos) END END CheckType; @@ -2798,12 +2854,12 @@ VAR label.self := IL.NewLabel(); getpos(parser, pos1); - range.a := Label(parser, caseExpr, label.type); + range.a := Label(parser, caseExpr, label._type); IF parser.sym = SCAN.lxRANGE THEN PARS.check1(~isRecPtr(caseExpr), parser, 53); NextPos(parser, pos); - range.b := Label(parser, caseExpr, label.type); + range.b := Label(parser, caseExpr, label._type); PARS.check(range.a <= range.b, pos, 103) ELSE range.b := range.a @@ -2812,7 +2868,7 @@ VAR label.range := range; IF isRecPtr(caseExpr) THEN - CheckType(tree, label.type, parser, pos1) + CheckType(tree, label._type, parser, pos1) END; tree := AVL.insert(tree, label, LabelCmp, newnode, node); PARS.check(newnode, pos1, 100) @@ -2843,10 +2899,10 @@ VAR END CaseLabelList; - PROCEDURE case (parser: PARS.PARSER; caseExpr: PARS.EXPR; VAR tree: AVL.NODE; end: INTEGER); + PROCEDURE _case (parser: PARS.PARSER; caseExpr: PARS.EXPR; VAR tree: AVL.NODE; _end: INTEGER); VAR sym: INTEGER; - t: PROG.TYPE_; + t: PROG._TYPE; variant: INTEGER; node: AVL.NODE; last: IL.COMMAND; @@ -2859,8 +2915,8 @@ VAR PARS.checklex(parser, SCAN.lxCOLON); PARS.Next(parser); IF isRecPtr(caseExpr) THEN - t := caseExpr.type; - caseExpr.ident.type := node.data(CASE_LABEL).type + t := caseExpr._type; + caseExpr.ident._type := node.data(CASE_LABEL)._type END; last := IL.getlast(); @@ -2871,16 +2927,16 @@ VAR END; parser.StatSeq(parser); - IL.AddJmpCmd(IL.opJMP, end); + IL.AddJmpCmd(IL.opJMP, _end); IF isRecPtr(caseExpr) THEN - caseExpr.ident.type := t + caseExpr.ident._type := t END END - END case; + END _case; - PROCEDURE Table (node: AVL.NODE; else: INTEGER); + PROCEDURE Table (node: AVL.NODE; _else: INTEGER); VAR L, R: INTEGER; range: RANGE; @@ -2897,14 +2953,14 @@ VAR IF left # NIL THEN L := left.data(CASE_LABEL).self ELSE - L := else + L := _else END; right := node.right; IF right # NIL THEN R := right.data(CASE_LABEL).self ELSE - R := else + R := _else END; last := IL.getlast(); @@ -2918,7 +2974,7 @@ VAR IL.setlast(v.cmd); IL.SetLabel(node.data(CASE_LABEL).self); - IL.case(range.a, range.b, L, R); + IL._case(range.a, range.b, L, R); IF v.processed THEN IL.AddJmpCmd(IL.opJMP, node.data(CASE_LABEL).variant) END; @@ -2926,8 +2982,8 @@ VAR IL.setlast(last); - Table(left, else); - Table(right, else) + Table(left, _else); + Table(right, _else) END END Table; @@ -2935,8 +2991,7 @@ VAR PROCEDURE TableT (node: AVL.NODE); BEGIN IF node # NIL THEN - IL.caset(node.data(CASE_LABEL).range.a, node.data(CASE_LABEL).variant); - + IL.AddCmd2(IL.opCASET, node.data(CASE_LABEL).variant, node.data(CASE_LABEL).range.a); TableT(node.left); TableT(node.right) END @@ -2945,31 +3000,31 @@ VAR PROCEDURE ParseCase (parser: PARS.PARSER; e: PARS.EXPR; pos: PARS.POSITION); VAR - table, end, else: INTEGER; + table, _end, _else: INTEGER; tree: AVL.NODE; item: LISTS.ITEM; BEGIN LISTS.push(CaseVariants, NewVariant(0, NIL)); - end := IL.NewLabel(); - else := IL.NewLabel(); + _end := IL.NewLabel(); + _else := IL.NewLabel(); table := IL.NewLabel(); IL.AddCmd(IL.opSWITCH, ORD(isRecPtr(e))); IL.AddJmpCmd(IL.opJMP, table); tree := NIL; - case(parser, e, tree, end); + _case(parser, e, tree, _end); WHILE parser.sym = SCAN.lxBAR DO PARS.Next(parser); - case(parser, e, tree, end) + _case(parser, e, tree, _end) END; - IL.SetLabel(else); + IL.SetLabel(_else); IF parser.sym = SCAN.lxELSE THEN PARS.Next(parser); parser.StatSeq(parser); - IL.AddJmpCmd(IL.opJMP, end) + IL.AddJmpCmd(IL.opJMP, _end) ELSE IL.OnError(pos.line, errCASE) END; @@ -2980,14 +3035,14 @@ VAR IF isRecPtr(e) THEN IL.SetLabel(table); TableT(tree); - IL.AddJmpCmd(IL.opJMP, else) + IL.AddJmpCmd(IL.opJMP, _else) ELSE tree.data(CASE_LABEL).self := table; - Table(tree, else) + Table(tree, _else) END; AVL.destroy(tree, DestroyLabel); - IL.SetLabel(end); + IL.SetLabel(_end); IL.AddCmd0(IL.opENDSW); REPEAT @@ -3048,13 +3103,13 @@ BEGIN ident := PROG.getIdent(parser.unit, parser.lex.ident, TRUE); PARS.check1(ident # NIL, parser, 48); PARS.check1(ident.typ = PROG.idVAR, parser, 93); - PARS.check1(ident.type = tINTEGER, parser, 97); + PARS.check1(ident._type = tINTEGER, parser, 97); PARS.ExpectSym(parser, SCAN.lxASSIGN); NextPos(parser, pos); expression(parser, e); PARS.check(isInt(e), pos, 76); - offset := PROG.getOffset(PARS.program, ident); + offset := PROG.getOffset(ident); IF ident.global THEN IL.AddCmd(IL.opGADR, offset) @@ -3075,7 +3130,7 @@ BEGIN ELSE IL.AddCmd(IL.opLADR, -offset) END; - IL.load(ident.type.size); + IL.load(ident._type.size); PARS.checklex(parser, SCAN.lxTO); NextPos(parser, pos2); @@ -3112,7 +3167,7 @@ BEGIN END END; - IL.AddJmpCmd(IL.opJNE, L2); + IL.AddJmpCmd(IL.opJZ, L2); PARS.checklex(parser, SCAN.lxDO); PARS.Next(parser); @@ -3171,7 +3226,7 @@ BEGIN END StatSeq; -PROCEDURE chkreturn (parser: PARS.PARSER; e: PARS.EXPR; t: PROG.TYPE_; pos: PARS.POSITION): BOOLEAN; +PROCEDURE chkreturn (parser: PARS.PARSER; e: PARS.EXPR; t: PROG._TYPE; pos: PARS.POSITION): BOOLEAN; VAR res: BOOLEAN; @@ -3179,24 +3234,20 @@ BEGIN res := assigncomp(e, t); IF res THEN IF e.obj = eCONST THEN - IF e.type = tREAL THEN - IL.Float(ARITH.Float(e.value)) - ELSIF e.type.typ = PROG.tNIL THEN + IF e._type = tREAL THEN + Float(parser, e) + ELSIF e._type.typ = PROG.tNIL THEN IL.Const(0) ELSE LoadConst(e) END - ELSIF (e.type = tINTEGER) & (t = tBYTE) & (chkBYTE IN Options.checking) THEN + ELSIF (e._type = tINTEGER) & (t = tBYTE) & (chkBYTE IN Options.checking) THEN CheckRange(256, pos.line, errBYTE) ELSIF e.obj = ePROC THEN PARS.check(e.ident.global, pos, 85); IL.PushProc(e.ident.proc.label) ELSIF e.obj = eIMP THEN - IL.PushImpProc(e.ident.import) - END; - - IF e.type = tREAL THEN - IL.retf + IL.PushImpProc(e.ident._import) END END @@ -3216,8 +3267,8 @@ VAR BEGIN id := PROG.getIdent(rtl, SCAN.enterid(name), FALSE); - IF (id # NIL) & (id.import # NIL) THEN - IL.set_rtl(idx, -id.import(IL.IMPORT_PROC).label); + IF (id # NIL) & (id._import # NIL) THEN + IL.set_rtl(idx, -id._import(IL.IMPORT_PROC).label); id.proc.used := TRUE ELSIF (id # NIL) & (id.proc # NIL) THEN IL.set_rtl(idx, id.proc.label); @@ -3229,7 +3280,7 @@ VAR BEGIN - rtl := PARS.program.rtl; + rtl := PROG.program.rtl; ASSERT(rtl # NIL); getproc(rtl, "_strcmp", IL._strcmp); @@ -3256,7 +3307,7 @@ BEGIN getproc(rtl, "_isrec", IL._isrec); getproc(rtl, "_dllentry", IL._dllentry); getproc(rtl, "_sofinit", IL._sofinit) - ELSIF CPU = TARGETS.cpuTHUMB THEN + ELSIF CPU IN {TARGETS.cpuTHUMB, TARGETS.cpuRVM32I} THEN getproc(rtl, "_fmul", IL._fmul); getproc(rtl, "_fdiv", IL._fdiv); getproc(rtl, "_fdivi", IL._fdivi); @@ -3267,7 +3318,10 @@ BEGIN getproc(rtl, "_floor", IL._floor); getproc(rtl, "_flt", IL._flt); getproc(rtl, "_pack", IL._pack); - getproc(rtl, "_unpk", IL._unpk) + getproc(rtl, "_unpk", IL._unpk); + IF CPU = TARGETS.cpuRVM32I THEN + getproc(rtl, "_error", IL._error) + END END END setrtl; @@ -3279,13 +3333,13 @@ VAR ext: PARS.PATH; BEGIN - tINTEGER := PARS.program.stTypes.tINTEGER; - tBYTE := PARS.program.stTypes.tBYTE; - tCHAR := PARS.program.stTypes.tCHAR; - tSET := PARS.program.stTypes.tSET; - tBOOLEAN := PARS.program.stTypes.tBOOLEAN; - tWCHAR := PARS.program.stTypes.tWCHAR; - tREAL := PARS.program.stTypes.tREAL; + tINTEGER := PROG.program.stTypes.tINTEGER; + tBYTE := PROG.program.stTypes.tBYTE; + tCHAR := PROG.program.stTypes.tCHAR; + tSET := PROG.program.stTypes.tSET; + tBOOLEAN := PROG.program.stTypes.tBOOLEAN; + tWCHAR := PROG.program.stTypes.tWCHAR; + tREAL := PROG.program.stTypes.tREAL; Options := options; CPU := TARGETS.CPU; @@ -3299,7 +3353,7 @@ BEGIN IL.init(CPU); - IF CPU # TARGETS.cpuMSP430 THEN + IF TARGETS.RTL THEN parser := PARS.create(path, lib_path, StatSeq, expression, designator, chkreturn); IF parser.open(parser, UTILS.RTL_NAME) THEN parser.parse(parser); @@ -3327,23 +3381,24 @@ BEGIN PARS.destroy(parser); - IF PARS.program.bss > UTILS.MAX_GLOBAL_SIZE THEN + IF PROG.program.bss > UTILS.MAX_GLOBAL_SIZE THEN ERRORS.Error(204) END; - IF CPU # TARGETS.cpuMSP430 THEN + IF TARGETS.RTL THEN setrtl END; - PROG.DelUnused(PARS.program, IL.DelImport); + PROG.DelUnused(IL.DelImport); - IL.set_bss(PARS.program.bss); + IL.set_bss(PROG.program.bss); CASE CPU OF |TARGETS.cpuAMD64: AMD64.CodeGen(outname, target, options) |TARGETS.cpuX86: X86.CodeGen(outname, target, options) |TARGETS.cpuMSP430: MSP430.CodeGen(outname, target, options) |TARGETS.cpuTHUMB: THUMB.CodeGen(outname, target, options) + |TARGETS.cpuRVM32I: RVM32I.CodeGen(outname, target, options) END END compile; diff --git a/programs/develop/oberon07/Source/STRINGS.ob07 b/programs/develop/oberon07/Source/STRINGS.ob07 index af3baaeb4..8dfcb66d0 100644 --- a/programs/develop/oberon07/Source/STRINGS.ob07 +++ b/programs/develop/oberon07/Source/STRINGS.ob07 @@ -10,9 +10,20 @@ MODULE STRINGS; IMPORT UTILS; +PROCEDURE copy* (src: ARRAY OF CHAR; VAR dst: ARRAY OF CHAR; spos, dpos, count: INTEGER); +BEGIN + WHILE count > 0 DO + dst[dpos] := src[spos]; + INC(spos); + INC(dpos); + DEC(count) + END +END copy; + + PROCEDURE append* (VAR s1: ARRAY OF CHAR; s2: ARRAY OF CHAR); VAR - n1, n2, i, j: INTEGER; + n1, n2: INTEGER; BEGIN n1 := LENGTH(s1); @@ -20,43 +31,14 @@ BEGIN ASSERT(n1 + n2 < LEN(s1)); - i := 0; - j := n1; - WHILE i < n2 DO - s1[j] := s2[i]; - INC(i); - INC(j) - END; - - s1[j] := 0X - + copy(s2, s1, 0, n1, n2); + s1[n1 + n2] := 0X END append; -PROCEDURE reverse (VAR s: ARRAY OF CHAR); -VAR - i, j: INTEGER; - a, b: CHAR; - -BEGIN - i := 0; - j := LENGTH(s) - 1; - - WHILE i < j DO - a := s[i]; - b := s[j]; - s[i] := b; - s[j] := a; - INC(i); - DEC(j) - END -END reverse; - - PROCEDURE IntToStr* (x: INTEGER; VAR str: ARRAY OF CHAR); VAR i, a: INTEGER; - minus: BOOLEAN; BEGIN IF x = UTILS.minint THEN @@ -67,65 +49,41 @@ BEGIN END ELSE - - minus := x < 0; - IF minus THEN - x := -x - END; i := 0; - a := 0; - REPEAT - str[i] := CHR(x MOD 10 + ORD("0")); - x := x DIV 10; - INC(i) - UNTIL x = 0; - - IF minus THEN - str[i] := "-"; - INC(i) + IF x < 0 THEN + x := -x; + i := 1; + str[0] := "-" END; + a := x; + REPEAT + INC(i); + a := a DIV 10 + UNTIL a = 0; + str[i] := 0X; - reverse(str) + REPEAT + DEC(i); + str[i] := CHR(x MOD 10 + ORD("0")); + x := x DIV 10 + UNTIL x = 0 END END IntToStr; -PROCEDURE hexdgt (n: BYTE): BYTE; -BEGIN - IF n < 10 THEN - n := n + ORD("0") - ELSE - n := n - 10 + ORD("A") - END - - RETURN n -END hexdgt; - - PROCEDURE IntToHex* (x: INTEGER; VAR str: ARRAY OF CHAR; n: INTEGER); BEGIN str[n] := 0X; WHILE n > 0 DO - str[n - 1] := CHR(hexdgt(x MOD 16)); + str[n - 1] := CHR(UTILS.hexdgt(x MOD 16)); x := x DIV 16; DEC(n) END END IntToHex; -PROCEDURE copy* (src: ARRAY OF CHAR; VAR dst: ARRAY OF CHAR; spos, dpos, count: INTEGER); -BEGIN - WHILE count > 0 DO - dst[dpos] := src[spos]; - INC(spos); - INC(dpos); - DEC(count) - END -END copy; - - PROCEDURE search* (s: ARRAY OF CHAR; VAR pos: INTEGER; c: CHAR; forward: BOOLEAN); VAR length: INTEGER; @@ -185,10 +143,10 @@ VAR i: INTEGER; BEGIN - i := 0; - WHILE (i < LEN(str)) & (str[i] # 0X) DO + i := LENGTH(str) - 1; + WHILE i >= 0 DO cap(str[i]); - INC(i) + DEC(i) END END UpCase; diff --git a/programs/develop/oberon07/Source/TARGETS.ob07 b/programs/develop/oberon07/Source/TARGETS.ob07 index 39ceed4eb..58d7e0183 100644 --- a/programs/develop/oberon07/Source/TARGETS.ob07 +++ b/programs/develop/oberon07/Source/TARGETS.ob07 @@ -24,12 +24,18 @@ CONST Linux64* = 11; Linux64SO* = 12; STM32CM3* = 13; + RVM32I* = 14; cpuX86* = 0; cpuAMD64* = 1; cpuMSP430* = 2; cpuTHUMB* = 3; + cpuRVM32I* = 4; osNONE* = 0; osWIN32* = 1; osWIN64* = 2; osLINUX32* = 3; osLINUX64* = 4; osKOS* = 5; + noDISPOSE = {MSP430, STM32CM3, RVM32I}; + + noRTL = {MSP430}; + TYPE @@ -37,7 +43,7 @@ TYPE TARGET = RECORD - target, CPU, BitDepth, OS, RealSize: INTEGER; + target, CPU, OS, RealSize: INTEGER; ComLinePar*, LibDir, FileExt: STRING END; @@ -45,18 +51,23 @@ TYPE VAR - Targets*: ARRAY 14 OF TARGET; + Targets*: ARRAY 15 OF TARGET; - target*, CPU*, BitDepth*, OS*, RealSize*, WordSize*, AdrSize*: INTEGER; + CPUs: ARRAY 5 OF + RECORD + BitDepth, InstrSize: INTEGER; + LittleEndian: BOOLEAN + END; + + target*, CPU*, BitDepth*, OS*, RealSize*, WordSize*, AdrSize*, InstrSize*: INTEGER; ComLinePar*, LibDir*, FileExt*: STRING; - Import*, Dispose*, Dll*: BOOLEAN; + Import*, Dispose*, RTL*, Dll*, LittleEndian*: BOOLEAN; -PROCEDURE Enter (idx, CPU, BitDepth, RealSize, OS: INTEGER; ComLinePar, LibDir, FileExt: STRING); +PROCEDURE Enter (idx, CPU, RealSize, OS: INTEGER; ComLinePar, LibDir, FileExt: STRING); BEGIN Targets[idx].target := idx; Targets[idx].CPU := CPU; - Targets[idx].BitDepth := BitDepth; Targets[idx].RealSize := RealSize; Targets[idx].OS := OS; Targets[idx].ComLinePar := ComLinePar; @@ -80,7 +91,9 @@ BEGIN IF res THEN target := Targets[i].target; CPU := Targets[i].CPU; - BitDepth := Targets[i].BitDepth; + BitDepth := CPUs[CPU].BitDepth; + InstrSize := CPUs[CPU].InstrSize; + LittleEndian := CPUs[CPU].LittleEndian; RealSize := Targets[i].RealSize; OS := Targets[i].OS; ComLinePar := Targets[i].ComLinePar; @@ -88,7 +101,8 @@ BEGIN FileExt := Targets[i].FileExt; Import := OS IN {osWIN32, osWIN64, osKOS}; - Dispose := ~(target IN {MSP430, STM32CM3}); + Dispose := ~(target IN noDISPOSE); + RTL := ~(target IN noRTL); Dll := target IN {Linux32SO, Linux64SO, Win32DLL, Win64DLL, KolibriOSDLL}; WordSize := BitDepth DIV 8; AdrSize := WordSize @@ -98,19 +112,34 @@ BEGIN END Select; +PROCEDURE EnterCPU (cpu, BitDepth, InstrSize: INTEGER; LittleEndian: BOOLEAN); BEGIN - Enter( MSP430, cpuMSP430, 16, 0, osNONE, "msp430", "MSP430", ".hex"); - Enter( Win32C, cpuX86, 32, 8, osWIN32, "win32con", "Windows32", ".exe"); - Enter( Win32GUI, cpuX86, 32, 8, osWIN32, "win32gui", "Windows32", ".exe"); - Enter( Win32DLL, cpuX86, 32, 8, osWIN32, "win32dll", "Windows32", ".dll"); - Enter( KolibriOS, cpuX86, 32, 8, osKOS, "kosexe", "KolibriOS", ""); - Enter( KolibriOSDLL, cpuX86, 32, 8, osKOS, "kosdll", "KolibriOS", ".obj"); - Enter( Win64C, cpuAMD64, 64, 8, osWIN64, "win64con", "Windows64", ".exe"); - Enter( Win64GUI, cpuAMD64, 64, 8, osWIN64, "win64gui", "Windows64", ".exe"); - Enter( Win64DLL, cpuAMD64, 64, 8, osWIN64, "win64dll", "Windows64", ".dll"); - Enter( Linux32, cpuX86, 32, 8, osLINUX32, "linux32exe", "Linux32", ""); - Enter( Linux32SO, cpuX86, 32, 8, osLINUX32, "linux32so", "Linux32", ".so"); - Enter( Linux64, cpuAMD64, 64, 8, osLINUX64, "linux64exe", "Linux64", ""); - Enter( Linux64SO, cpuAMD64, 64, 8, osLINUX64, "linux64so", "Linux64", ".so"); - Enter( STM32CM3, cpuTHUMB, 32, 4, osNONE, "stm32cm3", "STM32CM3", ".hex"); + CPUs[cpu].BitDepth := BitDepth; + CPUs[cpu].InstrSize := InstrSize; + CPUs[cpu].LittleEndian := LittleEndian +END EnterCPU; + + +BEGIN + EnterCPU(cpuX86, 32, 1, TRUE); + EnterCPU(cpuAMD64, 64, 1, TRUE); + EnterCPU(cpuMSP430, 16, 2, TRUE); + EnterCPU(cpuTHUMB, 32, 2, TRUE); + EnterCPU(cpuRVM32I, 32, 4, TRUE); + + Enter( MSP430, cpuMSP430, 0, osNONE, "msp430", "MSP430", ".hex"); + Enter( Win32C, cpuX86, 8, osWIN32, "win32con", "Windows32", ".exe"); + Enter( Win32GUI, cpuX86, 8, osWIN32, "win32gui", "Windows32", ".exe"); + Enter( Win32DLL, cpuX86, 8, osWIN32, "win32dll", "Windows32", ".dll"); + Enter( KolibriOS, cpuX86, 8, osKOS, "kosexe", "KolibriOS", ""); + Enter( KolibriOSDLL, cpuX86, 8, osKOS, "kosdll", "KolibriOS", ".obj"); + Enter( Win64C, cpuAMD64, 8, osWIN64, "win64con", "Windows64", ".exe"); + Enter( Win64GUI, cpuAMD64, 8, osWIN64, "win64gui", "Windows64", ".exe"); + Enter( Win64DLL, cpuAMD64, 8, osWIN64, "win64dll", "Windows64", ".dll"); + Enter( Linux32, cpuX86, 8, osLINUX32, "linux32exe", "Linux32", ""); + Enter( Linux32SO, cpuX86, 8, osLINUX32, "linux32so", "Linux32", ".so"); + Enter( Linux64, cpuAMD64, 8, osLINUX64, "linux64exe", "Linux64", ""); + Enter( Linux64SO, cpuAMD64, 8, osLINUX64, "linux64so", "Linux64", ".so"); + Enter( STM32CM3, cpuTHUMB, 4, osNONE, "stm32cm3", "STM32CM3", ".hex"); + Enter( RVM32I, cpuRVM32I, 4, osNONE, "rvm32i", "RVM32I", ".bin"); END TARGETS. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/TEXTDRV.ob07 b/programs/develop/oberon07/Source/TEXTDRV.ob07 index 9ae8b68c3..7f2c416dd 100644 --- a/programs/develop/oberon07/Source/TEXTDRV.ob07 +++ b/programs/develop/oberon07/Source/TEXTDRV.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018-2019, Anton Krotov + Copyright (c) 2018-2020, Anton Krotov All rights reserved. *) @@ -28,9 +28,16 @@ TYPE CR: BOOLEAN; line*, col*: INTEGER; + ifc*: INTEGER; + elsec*: INTEGER; eof*: BOOLEAN; eol*: BOOLEAN; - peak*: CHAR + skip*: BOOLEAN; + peak*: CHAR; + _skip*, + _elsif*, + _else*: ARRAY 100 OF BOOLEAN; + fname*: ARRAY 2048 OF CHAR END; @@ -161,8 +168,13 @@ BEGIN text.col := 1; text.eof := FALSE; text.eol := FALSE; + text.skip := FALSE; + text.ifc := 0; + text.elsec := 0; + text._skip[0] := FALSE; text.peak := 0X; text.file := FILES.open(name); + COPY(name, text.fname); IF text.file # NIL THEN load(text); init(text) diff --git a/programs/develop/oberon07/Source/THUMB.ob07 b/programs/develop/oberon07/Source/THUMB.ob07 index d9e8ba9ec..cfc3a52f6 100644 --- a/programs/develop/oberon07/Source/THUMB.ob07 +++ b/programs/develop/oberon07/Source/THUMB.ob07 @@ -616,14 +616,14 @@ VAR PROCEDURE SetIV (idx, label, CodeAdr: INTEGER); VAR - l, h: ANYCODE; + l, h: LISTS.ITEM; BEGIN - l := CodeList.first(ANYCODE); - h := l.next(ANYCODE); + l := CodeList.first; + h := l.next; WHILE idx > 0 DO - l := h.next(ANYCODE); - h := l.next(ANYCODE); + l := h.next; + h := l.next; DEC(idx) END; label := BIN.GetLabel(program, label) * 2 + CodeAdr + 1; @@ -719,7 +719,7 @@ BEGIN PutCode(second) END - |JCC: genbc(code) + |JCC: genbc(code) |CBXZ: IF code.len > 1 THEN @@ -784,8 +784,9 @@ END mov; PROCEDURE xchg (r1, r2: INTEGER); BEGIN - push(r1); push(r2); - pop(r1); pop(r2) + push(r1); + mov(r1, r2); + pop(r2) END xchg; @@ -1092,7 +1093,7 @@ BEGIN |IL.opCALLP: UnOp(r1); - AddImm8(r1, 1); + AddImm8(r1, 1); (* Thumb mode *) gen5(3, TRUE, FALSE, r1, 0); (* blx r1 *) drop; ASSERT(R.top = -1) @@ -1176,7 +1177,7 @@ BEGIN |IL.opERR: call(genTrap) - |IL.opNOP: + |IL.opNOP, IL.opAND, IL.opOR: |IL.opSADR: reloc(GetAnyReg(), BIN.RDATA + pic, stroffs + param2) @@ -1347,37 +1348,25 @@ BEGIN SetCC(jne, r1) END - |IL.opACC: - IF (R.top # 0) OR (R.stk[0] # ACC) THEN - PushAll(0); - GetRegA; - pop(ACC); - DEC(R.pushed) - END - |IL.opDROP: UnOp(r1); drop - |IL.opJNZ: + |IL.opJNZ1: UnOp(r1); cbnz(r1, param1) - |IL.opJZ: - UnOp(r1); - cbz(r1, param1) - |IL.opJG: UnOp(r1); Tst(r1); jcc(jg, param1) - |IL.opJE: + |IL.opJNZ: UnOp(r1); cbnz(r1, param1); drop - |IL.opJNE: + |IL.opJZ: UnOp(r1); cbz(r1, param1); drop @@ -1435,10 +1424,10 @@ BEGIN cc := cond(opcode); next := cmd.next(COMMAND); - IF next.opcode = IL.opJE THEN + IF next.opcode = IL.opJNZ THEN jcc(cc, next.param1); cmd := next - ELSIF next.opcode = IL.opJNE THEN + ELSIF next.opcode = IL.opJZ THEN jcc(inv0(cc), next.param1); cmd := next ELSE @@ -1487,7 +1476,7 @@ BEGIN END; drop - |IL.opADDL, IL.opADDR: + |IL.opADDC: UnOp(r1); AddConst(r1, param2) @@ -1761,7 +1750,7 @@ BEGIN gen4(14, r2, r1); (* bic r1, r2 *) drop - |IL.opADDSL, IL.opADDSR: + |IL.opADDSC: MovConst(GetAnyReg(), param2); BinOp(r1, r2); gen4(12, r2, r1); (* orr r1, r2 *) @@ -2014,7 +2003,7 @@ BEGIN CallRTL(IL._fdivi, 2); GetRegA - |IL.opADDF, IL.opADDFI: + |IL.opADDF: PushAll(2); CallRTL(IL._fadd, 2); GetRegA @@ -2336,8 +2325,6 @@ VAR DataAdr, BssAdr, DataSize, BssSize, CodeSize: INTEGER; - File: WR.FILE; - BEGIN IF target = TARGETS.STM32CM3 THEN CortexM3 @@ -2387,12 +2374,12 @@ BEGIN ERRORS.Error(204) END; - File := WR.Create(outname); + WR.Create(outname); - HEX.Data2(File, program.code, 0, CodeSize, high(Target.FlashAdr)); - HEX.End(File); + HEX.Data2(program.code, 0, CodeSize, high(Target.FlashAdr)); + HEX.End; - WR.Close(File); + WR.Close; C.StringLn("--------------------------------------------"); C.String( " rom: "); C.Int(CodeSize); C.String(" of "); C.Int(rom); C.String(" ("); C.Int(CodeSize * 100 DIV rom); C.StringLn("%)"); diff --git a/programs/develop/oberon07/Source/UTILS.ob07 b/programs/develop/oberon07/Source/UTILS.ob07 index 81c04ceaf..6b77353cb 100644 --- a/programs/develop/oberon07/Source/UTILS.ob07 +++ b/programs/develop/oberon07/Source/UTILS.ob07 @@ -13,18 +13,17 @@ IMPORT HOST; CONST slash* = HOST.slash; + eol* = HOST.eol; bit_depth* = HOST.bit_depth; maxint* = HOST.maxint; minint* = HOST.minint; - OS = HOST.OS; - min32* = -2147483647-1; max32* = 2147483647; vMajor* = 1; - vMinor* = 29; + vMinor* = 43; FILE_EXT* = ".ob07"; RTL_NAME* = "RTL"; @@ -32,17 +31,10 @@ CONST MAX_GLOBAL_SIZE* = 1600000000; -TYPE - - DAYS = ARRAY 12, 31, 2 OF INTEGER; - - VAR time*: INTEGER; - eol*: ARRAY 3 OF CHAR; - maxreal*: REAL; target*: @@ -61,8 +53,6 @@ VAR bit_diff*: INTEGER; - days: DAYS; - PROCEDURE FileRead* (F: INTEGER; VAR Buffer: ARRAY OF CHAR; bytes: INTEGER): INTEGER; RETURN HOST.FileRead(F, Buffer, bytes) @@ -90,6 +80,12 @@ PROCEDURE FileOpen* (FName: ARRAY OF CHAR): INTEGER; END FileOpen; +PROCEDURE chmod* (FName: ARRAY OF CHAR); +BEGIN + HOST.chmod(FName) +END chmod; + + PROCEDURE GetArg* (i: INTEGER; VAR str: ARRAY OF CHAR); BEGIN HOST.GetArg(i, str) @@ -134,25 +130,8 @@ BEGIN END GetCurrentDirectory; -PROCEDURE GetUnixTime* (year, month, day, hour, min, sec: INTEGER): INTEGER; - RETURN ((year - 1970) * 365 + days[month - 1, day - 1, ORD(year DIV 4 = 0)] + (year - 1969) DIV 4) * 86400 + hour * 3600 + min * 60 + sec -END GetUnixTime; - - PROCEDURE UnixTime* (): INTEGER; -VAR - year, month, day, hour, min, sec: INTEGER; - res: INTEGER; - -BEGIN - IF OS = "LINUX" THEN - res := HOST.UnixTime() - ELSE - HOST.now(year, month, day, hour, min, sec); - res := GetUnixTime(year, month, day, hour, min, sec) - END - - RETURN res + RETURN HOST.UnixTime() END UnixTime; @@ -229,51 +208,19 @@ BEGIN END Log2; -PROCEDURE init (VAR days: DAYS); -VAR - i, j, n0, n1: INTEGER; - +PROCEDURE hexdgt* (n: BYTE): BYTE; BEGIN - - FOR i := 0 TO 11 DO - FOR j := 0 TO 30 DO - days[i, j, 0] := 0; - days[i, j, 1] := 0; - END - END; - - days[ 1, 28, 0] := -1; - - FOR i := 0 TO 1 DO - days[ 1, 29, i] := -1; - days[ 1, 30, i] := -1; - days[ 3, 30, i] := -1; - days[ 5, 30, i] := -1; - days[ 8, 30, i] := -1; - days[10, 30, i] := -1; - END; - - n0 := 0; - n1 := 0; - FOR i := 0 TO 11 DO - FOR j := 0 TO 30 DO - IF days[i, j, 0] = 0 THEN - days[i, j, 0] := n0; - INC(n0) - END; - IF days[i, j, 1] = 0 THEN - days[i, j, 1] := n1; - INC(n1) - END - END + IF n < 10 THEN + INC(n, ORD("0")) + ELSE + INC(n, ORD("A") - 10) END -END init; + RETURN n +END hexdgt; BEGIN time := GetTickCount(); - COPY(HOST.eol, eol); - maxreal := HOST.maxreal; - init(days) + maxreal := HOST.maxreal END UTILS. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/WRITER.ob07 b/programs/develop/oberon07/Source/WRITER.ob07 index 58329005f..bfb180676 100644 --- a/programs/develop/oberon07/Source/WRITER.ob07 +++ b/programs/develop/oberon07/Source/WRITER.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018-2019, Anton Krotov + Copyright (c) 2018-2020, Anton Krotov All rights reserved. *) @@ -10,27 +10,23 @@ MODULE WRITER; IMPORT FILES, ERRORS, UTILS; -TYPE - - FILE* = FILES.FILE; - - VAR counter*: INTEGER; + file: FILES.FILE; -PROCEDURE align (n, _align: INTEGER): INTEGER; +PROCEDURE align* (n, _align: INTEGER): INTEGER; BEGIN IF n MOD _align # 0 THEN - n := n + _align - (n MOD _align) + INC(n, _align - (n MOD _align)) END RETURN n END align; -PROCEDURE WriteByte* (file: FILE; n: BYTE); +PROCEDURE WriteByte* (n: BYTE); BEGIN IF FILES.WriteByte(file, n) THEN INC(counter) @@ -40,7 +36,7 @@ BEGIN END WriteByte; -PROCEDURE Write* (file: FILE; chunk: ARRAY OF BYTE; bytes: INTEGER); +PROCEDURE Write* (chunk: ARRAY OF BYTE; bytes: INTEGER); VAR n: INTEGER; @@ -53,56 +49,56 @@ BEGIN END Write; -PROCEDURE Write64LE* (file: FILE; n: INTEGER); +PROCEDURE Write64LE* (n: INTEGER); VAR i: INTEGER; BEGIN FOR i := 0 TO 7 DO - WriteByte(file, UTILS.Byte(n, i)) + WriteByte(UTILS.Byte(n, i)) END END Write64LE; -PROCEDURE Write32LE* (file: FILE; n: INTEGER); +PROCEDURE Write32LE* (n: INTEGER); VAR i: INTEGER; BEGIN FOR i := 0 TO 3 DO - WriteByte(file, UTILS.Byte(n, i)) + WriteByte(UTILS.Byte(n, i)) END END Write32LE; -PROCEDURE Write16LE* (file: FILE; n: INTEGER); +PROCEDURE Write16LE* (n: INTEGER); BEGIN - WriteByte(file, UTILS.Byte(n, 0)); - WriteByte(file, UTILS.Byte(n, 1)) + WriteByte(UTILS.Byte(n, 0)); + WriteByte(UTILS.Byte(n, 1)) END Write16LE; -PROCEDURE Padding* (file: FILE; FileAlignment: INTEGER); +PROCEDURE Padding* (FileAlignment: INTEGER); VAR i: INTEGER; BEGIN i := align(counter, FileAlignment) - counter; WHILE i > 0 DO - WriteByte(file, 0); + WriteByte(0); DEC(i) END END Padding; -PROCEDURE Create* (FileName: ARRAY OF CHAR): FILE; +PROCEDURE Create* (FileName: ARRAY OF CHAR); BEGIN - counter := 0 - RETURN FILES.create(FileName) + counter := 0; + file := FILES.create(FileName) END Create; -PROCEDURE Close* (VAR file: FILE); +PROCEDURE Close*; BEGIN FILES.close(file) END Close; diff --git a/programs/develop/oberon07/Source/X86.ob07 b/programs/develop/oberon07/Source/X86.ob07 index 47cc4ae62..de1759228 100644 --- a/programs/develop/oberon07/Source/X86.ob07 +++ b/programs/develop/oberon07/Source/X86.ob07 @@ -8,7 +8,7 @@ MODULE X86; IMPORT IL, REG, UTILS, LISTS, BIN, PE32, KOS, MSCOFF, ELF, PROG, - CHL := CHUNKLISTS, PATHS, TARGETS; + CHL := CHUNKLISTS, PATHS, TARGETS, ERRORS; CONST @@ -22,6 +22,8 @@ CONST esp = 4; ebp = 5; + MAX_FR = 7; + sete = 94H; setne = 95H; setl = 9CH; setge = 9DH; setle = 9EH; setg = 9FH; setc = 92H; setnc = 93H; je = 84H; jne = 85H; jl = 8CH; jge = 8DH; jle = 8EH; jg = 8FH; jb = 82H; jnb = 83H; @@ -29,6 +31,8 @@ CONST CODECHUNK = 8; + FPR_ERR = 41; + TYPE @@ -92,6 +96,10 @@ VAR tcount: INTEGER; + FR: ARRAY 1000 OF INTEGER; + + fname: PATHS.PATH; + PROCEDURE OutByte* (n: BYTE); VAR @@ -146,7 +154,7 @@ BEGIN END OutWord; -PROCEDURE isByte (n: INTEGER): BOOLEAN; +PROCEDURE isByte* (n: INTEGER): BOOLEAN; RETURN (-128 <= n) & (n <= 127) END isByte; @@ -182,24 +190,24 @@ BEGIN END shift; -PROCEDURE mov (reg1, reg2: INTEGER); +PROCEDURE oprr (op: BYTE; reg1, reg2: INTEGER); (* op reg1, reg2 *) BEGIN - OutByte2(89H, 0C0H + reg2 * 8 + reg1) (* mov reg1, reg2 *) + OutByte2(op, 0C0H + 8 * reg2 + reg1) +END oprr; + + +PROCEDURE mov (reg1, reg2: INTEGER); (* mov reg1, reg2 *) +BEGIN + oprr(89H, reg1, reg2) END mov; -PROCEDURE xchg (reg1, reg2: INTEGER); -VAR - regs: SET; - +PROCEDURE xchg (reg1, reg2: INTEGER); (* xchg reg1, reg2 *) BEGIN - regs := {reg1, reg2}; - IF regs = {eax, ecx} THEN - OutByte(91H) (* xchg eax, ecx *) - ELSIF regs = {eax, edx} THEN - OutByte(92H) (* xchg eax, edx *) - ELSIF regs = {ecx, edx} THEN - OutByte2(87H, 0D1H) (* xchg ecx, edx *) + IF eax IN {reg1, reg2} THEN + OutByte(90H + reg1 + reg2) + ELSE + oprr(87H, reg1, reg2) END END xchg; @@ -216,14 +224,24 @@ BEGIN END push; +PROCEDURE xor (reg1, reg2: INTEGER); (* xor reg1, reg2 *) +BEGIN + oprr(31H, reg1, reg2) +END xor; + + PROCEDURE movrc (reg, n: INTEGER); BEGIN - OutByte(0B8H + reg); (* mov reg, n *) - OutInt(n) + IF n = 0 THEN + xor(reg, reg) + ELSE + OutByte(0B8H + reg); (* mov reg, n *) + OutInt(n) + END END movrc; -PROCEDURE pushc (n: INTEGER); +PROCEDURE pushc* (n: INTEGER); BEGIN OutByte(68H + short(n)); (* push n *) OutIntByte(n) @@ -248,69 +266,87 @@ BEGIN END not; -PROCEDURE add (reg1, reg2: INTEGER); +PROCEDURE add (reg1, reg2: INTEGER); (* add reg1, reg2 *) BEGIN - OutByte2(01H, 0C0H + reg2 * 8 + reg1) (* add reg1, reg2 *) + oprr(01H, reg1, reg2) END add; -PROCEDURE andrc (reg, n: INTEGER); +PROCEDURE oprc* (op, reg, n: INTEGER); BEGIN - OutByte2(81H + short(n), 0E0H + reg); (* and reg, n *) - OutIntByte(n) + IF (reg = eax) & ~isByte(n) THEN + CASE op OF + |0C0H: op := 05H (* add *) + |0E8H: op := 2DH (* sub *) + |0F8H: op := 3DH (* cmp *) + |0E0H: op := 25H (* and *) + |0C8H: op := 0DH (* or *) + |0F0H: op := 35H (* xor *) + END; + OutByte(op); + OutInt(n) + ELSE + OutByte2(81H + short(n), op + reg MOD 8); + OutIntByte(n) + END +END oprc; + + +PROCEDURE andrc (reg, n: INTEGER); (* and reg, n *) +BEGIN + oprc(0E0H, reg, n) END andrc; -PROCEDURE orrc (reg, n: INTEGER); +PROCEDURE orrc (reg, n: INTEGER); (* or reg, n *) BEGIN - OutByte2(81H + short(n), 0C8H + reg); (* or reg, n *) - OutIntByte(n) + oprc(0C8H, reg, n) END orrc; -PROCEDURE addrc (reg, n: INTEGER); +PROCEDURE xorrc (reg, n: INTEGER); (* xor reg, n *) BEGIN - OutByte2(81H + short(n), 0C0H + reg); (* add reg, n *) - OutIntByte(n) + oprc(0F0H, reg, n) +END xorrc; + + +PROCEDURE addrc (reg, n: INTEGER); (* add reg, n *) +BEGIN + oprc(0C0H, reg, n) END addrc; -PROCEDURE subrc (reg, n: INTEGER); +PROCEDURE subrc (reg, n: INTEGER); (* sub reg, n *) BEGIN - OutByte2(81H + short(n), 0E8H + reg); (* sub reg, n *) - OutIntByte(n) + oprc(0E8H, reg, n) END subrc; -PROCEDURE cmprr (reg1, reg2: INTEGER); -BEGIN - OutByte2(39H, 0C0H + reg2 * 8 + reg1) (* cmp reg1, reg2 *) -END cmprr; - - -PROCEDURE cmprc (reg, n: INTEGER); +PROCEDURE cmprc (reg, n: INTEGER); (* cmp reg, n *) BEGIN IF n = 0 THEN test(reg) ELSE - OutByte2(81H + short(n), 0F8H + reg); (* cmp reg, n *) - OutIntByte(n) + oprc(0F8H, reg, n) END END cmprc; -PROCEDURE setcc (cond, reg: INTEGER); +PROCEDURE cmprr (reg1, reg2: INTEGER); (* cmp reg1, reg2 *) BEGIN - OutByte3(0FH, cond, 0C0H + reg) (* setcc reg *) + oprr(39H, reg1, reg2) +END cmprr; + + +PROCEDURE setcc* (cc, reg: INTEGER); (* setcc reg *) +BEGIN + IF reg >= 8 THEN + OutByte(41H) + END; + OutByte3(0FH, cc, 0C0H + reg MOD 8) END setcc; -PROCEDURE xor (reg1, reg2: INTEGER); -BEGIN - OutByte2(31H, 0C0H + reg2 * 8 + reg1) (* xor reg1, reg2 *) -END xor; - - PROCEDURE ret*; BEGIN OutByte(0C3H) @@ -578,7 +614,7 @@ BEGIN OutByte2(0DAH, 0E9H); (* fucompp *) OutByte3(09BH, 0DFH, 0E0H); (* fstsw ax *) OutByte(09EH); (* sahf *) - movrc(eax, 0) + OutByte(0B8H); OutInt(0) (* mov eax, 0 *) END fcmp; @@ -694,7 +730,7 @@ PROCEDURE translate (pic: BOOLEAN; stroffs: INTEGER); VAR cmd, next: COMMAND; - reg1, reg2: INTEGER; + reg1, reg2, fr: INTEGER; n, a, b, label, cc: INTEGER; @@ -705,6 +741,8 @@ VAR BEGIN cmd := IL.codes.commands.first(COMMAND); + fr := -1; + WHILE cmd # NIL DO param1 := cmd.param1; @@ -738,16 +776,18 @@ BEGIN ASSERT(R.top = -1) |IL.opPRECALL: - n := param2; - IF (param1 # 0) & (n # 0) THEN + PushAll(0); + IF (param2 # 0) & (fr >= 0) THEN subrc(esp, 8) END; - WHILE n > 0 DO + INC(FR[0]); + FR[FR[0]] := fr + 1; + WHILE fr >= 0 DO subrc(esp, 8); OutByte3(0DDH, 01CH, 024H); (* fstp qword[esp] *) - DEC(n) + DEC(fr) END; - PushAll(0) + ASSERT(fr = -1) |IL.opALIGN16: ASSERT(eax IN R.regs); @@ -759,27 +799,31 @@ BEGIN END; push(eax) - |IL.opRES: + |IL.opRESF, IL.opRES: ASSERT(R.top = -1); - GetRegA; - n := param2; - WHILE n > 0 DO - OutByte3(0DDH, 004H, 024H); (* fld qword[esp] *) - addrc(esp, 8); - DEC(n) - END + ASSERT(fr = -1); + n := FR[FR[0]]; DEC(FR[0]); - |IL.opRESF: - n := param2; - IF n > 0 THEN - OutByte3(0DDH, 5CH + long(n * 8), 24H); - OutIntByte(n * 8); (* fstp qword[esp + n*8] *) - INC(n) + IF opcode = IL.opRESF THEN + INC(fr); + IF n > 0 THEN + OutByte3(0DDH, 5CH + long(n * 8), 24H); + OutIntByte(n * 8); (* fstp qword[esp + n*8] *) + DEC(fr); + INC(n) + END; + + IF fr + n > MAX_FR THEN + ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR) + END + ELSE + GetRegA END; WHILE n > 0 DO OutByte3(0DDH, 004H, 024H); (* fld qword[esp] *) addrc(esp, 8); + INC(fr); DEC(n) END @@ -816,6 +860,12 @@ BEGIN ASSERT(R.top = -1); + IF opcode = IL.opLEAVEF THEN + DEC(fr) + END; + + ASSERT(fr = -1); + IF param1 > 0 THEN mov(esp, ebp) END; @@ -849,9 +899,8 @@ BEGIN END |IL.opCLEANUP: - n := param2 * 4; - IF n # 0 THEN - addrc(esp, n) + IF param2 # 0 THEN + addrc(esp, param2 * 4) END |IL.opPOPSP: @@ -863,9 +912,14 @@ BEGIN |IL.opLABEL: SetLabel(param1) (* L: *) - |IL.opNOP: + |IL.opNOP, IL.opAND, IL.opOR: |IL.opGADR: + next := cmd.next(COMMAND); + IF next.opcode = IL.opADDC THEN + INC(param2, next.param2); + cmd := next + END; reg1 := GetAnyReg(); IF pic THEN Pic(reg1, BIN.PICBSS, param2) @@ -875,7 +929,12 @@ BEGIN END |IL.opLADR: + next := cmd.next(COMMAND); n := param2 * 4; + IF next.opcode = IL.opADDC THEN + INC(n, next.param2); + cmd := next + END; OutByte2(8DH, 45H + GetAnyReg() * 8 + long(n)); (* lea reg1, dword[ebp + n] *) OutIntByte(n) @@ -907,7 +966,6 @@ BEGIN drop |IL.opVLOAD32: - n := param2 * 4; reg1 := GetAnyReg(); movrm(reg1, ebp, param2 * 4); movrm(reg1, reg1, 0) @@ -979,7 +1037,7 @@ BEGIN add(reg1, reg2); drop - |IL.opADDL, IL.opADDR: + |IL.opADDC: IF param2 # 0 THEN UnOp(reg1); next := cmd.next(COMMAND); @@ -1010,18 +1068,17 @@ BEGIN |IL.opSUB: BinOp(reg1, reg2); - OutByte2(29H, 0C0H + reg2 * 8 + reg1); (* sub reg1, reg2 *) + oprr(29H, reg1, reg2); (* sub reg1, reg2 *) drop |IL.opSUBR, IL.opSUBL: UnOp(reg1); - n := param2; - IF n = 1 THEN + IF param2 = 1 THEN OutByte(48H + reg1) (* dec reg1 *) - ELSIF n = -1 THEN + ELSIF param2 = -1 THEN OutByte(40H + reg1) (* inc reg1 *) - ELSIF n # 0 THEN - subrc(reg1, n) + ELSIF param2 # 0 THEN + subrc(reg1, param2) END; IF opcode = IL.opSUBL THEN neg(reg1) @@ -1111,7 +1168,7 @@ BEGIN reg2 := GetAnyReg(); Pic(reg2, BIN.PICIMP, param2); pushm(reg2, 0); - OutByte2(08FH, reg1); (* pop dword[reg1] *) + OutByte2(08FH, reg1); (* pop dword[reg1] *) drop ELSE OutByte2(0FFH, 035H); (* push dword[L] *) @@ -1179,10 +1236,10 @@ BEGIN cc := cond(opcode); next := cmd.next(COMMAND); - IF next.opcode = IL.opJE THEN + IF next.opcode = IL.opJNZ THEN jcc(cc, next.param1); cmd := next - ELSIF next.opcode = IL.opJNE THEN + ELSIF next.opcode = IL.opJZ THEN jcc(inv0(cc), next.param1); cmd := next ELSE @@ -1212,40 +1269,27 @@ BEGIN END; andrc(reg1, 1) - |IL.opACC: - IF (R.top # 0) OR (R.stk[0] # eax) THEN - PushAll(0); - GetRegA; - pop(eax); - DEC(R.pushed) - END - |IL.opDROP: UnOp(reg1); drop - |IL.opJNZ: + |IL.opJNZ1: UnOp(reg1); test(reg1); jcc(jne, param1) - |IL.opJZ: - UnOp(reg1); - test(reg1); - jcc(je, param1) - |IL.opJG: UnOp(reg1); test(reg1); jcc(jg, param1) - |IL.opJE: + |IL.opJNZ: UnOp(reg1); test(reg1); jcc(jne, param1); drop - |IL.opJNE: + |IL.opJZ: UnOp(reg1); test(reg1); jcc(je, param1); @@ -1389,7 +1433,7 @@ BEGIN |IL.opMULS: BinOp(reg1, reg2); - OutByte2(21H, 0C0H + reg2 * 8 + reg1); (* and reg1, reg2 *) + oprr(21H, reg1, reg2); (* and reg1, reg2 *) drop |IL.opMULSC: @@ -1403,21 +1447,20 @@ BEGIN |IL.opDIVSC: UnOp(reg1); - OutByte2(81H + short(param2), 0F0H + reg1); (* xor reg1, n *) - OutIntByte(param2) + xorrc(reg1, param2) |IL.opADDS: BinOp(reg1, reg2); - OutByte2(9H, 0C0H + reg2 * 8 + reg1); (* or reg1, reg2 *) + oprr(9H, reg1, reg2); (* or reg1, reg2 *) drop |IL.opSUBS: BinOp(reg1, reg2); not(reg2); - OutByte2(21H, 0C0H + reg2 * 8 + reg1); (* and reg1, reg2 *) + oprr(21H, reg1, reg2); (* and reg1, reg2 *) drop - |IL.opADDSL, IL.opADDSR: + |IL.opADDSC: UnOp(reg1); orrc(reg1, param2) @@ -1508,9 +1551,15 @@ BEGIN |IL.opMAXC, IL.opMINC: UnOp(reg1); cmprc(reg1, param2); - OutByte2(07DH + ORD(opcode = IL.opMINC), 5); (* jge/jle L *) - movrc(reg1, param2) - (* L: *) + label := NewLabel(); + IF opcode = IL.opMINC THEN + cc := jle + ELSE + cc := jge + END; + jcc(cc, label); + movrc(reg1, param2); + SetLabel(label) |IL.opIN, IL.opINR: IF opcode = IL.opINR THEN @@ -1824,15 +1873,25 @@ BEGIN drop |IL.opPUSHF: + ASSERT(fr >= 0); + DEC(fr); subrc(esp, 8); OutByte3(0DDH, 01CH, 024H) (* fstp qword[esp] *) |IL.opLOADF: + INC(fr); + IF fr > MAX_FR THEN + ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR) + END; UnOp(reg1); OutByte2(0DDH, reg1); (* fld qword[reg1] *) drop |IL.opCONSTF: + INC(fr); + IF fr > MAX_FR THEN + ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR) + END; float := cmd.float; IF float = 0.0 THEN OutByte2(0D9H, 0EEH) (* fldz *) @@ -1850,35 +1909,55 @@ BEGIN END |IL.opSAVEF, IL.opSAVEFI: + ASSERT(fr >= 0); + DEC(fr); UnOp(reg1); OutByte2(0DDH, 018H + reg1); (* fstp qword[reg1] *) drop - |IL.opADDF, IL.opADDFI: + |IL.opADDF: + ASSERT(fr >= 1); + DEC(fr); OutByte2(0DEH, 0C1H) (* faddp st1, st *) |IL.opSUBF: + ASSERT(fr >= 1); + DEC(fr); OutByte2(0DEH, 0E9H) (* fsubp st1, st *) |IL.opSUBFI: + ASSERT(fr >= 1); + DEC(fr); OutByte2(0DEH, 0E1H) (* fsubrp st1, st *) |IL.opMULF: + ASSERT(fr >= 1); + DEC(fr); OutByte2(0DEH, 0C9H) (* fmulp st1, st *) |IL.opDIVF: + ASSERT(fr >= 1); + DEC(fr); OutByte2(0DEH, 0F9H) (* fdivp st1, st *) |IL.opDIVFI: + ASSERT(fr >= 1); + DEC(fr); OutByte2(0DEH, 0F1H) (* fdivrp st1, st *) |IL.opUMINF: + ASSERT(fr >= 0); OutByte2(0D9H, 0E0H) (* fchs *) |IL.opFABS: + ASSERT(fr >= 0); OutByte2(0D9H, 0E1H) (* fabs *) |IL.opFLT: + INC(fr); + IF fr > MAX_FR THEN + ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR) + END; UnOp(reg1); push(reg1); OutByte3(0DBH, 004H, 024H); (* fild dword[esp] *) @@ -1886,6 +1965,8 @@ BEGIN drop |IL.opFLOOR: + ASSERT(fr >= 0); + DEC(fr); subrc(esp, 8); OutByte2(09BH, 0D9H); OutByte3(07CH, 024H, 004H); (* fstcw word[esp+4] *) OutByte2(09BH, 0D9H); OutByte3(07CH, 024H, 006H); (* fstcw word[esp+6] *) @@ -1899,18 +1980,24 @@ BEGIN addrc(esp, 4) |IL.opEQF: + ASSERT(fr >= 1); + DEC(fr, 2); fcmp; OutByte2(07AH, 003H); (* jp L *) setcc(sete, al) (* L: *) |IL.opNEF: + ASSERT(fr >= 1); + DEC(fr, 2); fcmp; OutByte2(07AH, 003H); (* jp L *) setcc(setne, al) (* L: *) |IL.opLTF: + ASSERT(fr >= 1); + DEC(fr, 2); fcmp; OutByte2(07AH, 00EH); (* jp L *) setcc(setc, al); @@ -1921,6 +2008,8 @@ BEGIN (* L: *) |IL.opGTF: + ASSERT(fr >= 1); + DEC(fr, 2); fcmp; OutByte2(07AH, 00FH); (* jp L *) setcc(setc, al); @@ -1931,12 +2020,16 @@ BEGIN (* L: *) |IL.opLEF: + ASSERT(fr >= 1); + DEC(fr, 2); fcmp; OutByte2(07AH, 003H); (* jp L *) setcc(setnc, al) (* L: *) |IL.opGEF: + ASSERT(fr >= 1); + DEC(fr, 2); fcmp; OutByte2(07AH, 010H); (* jp L *) setcc(setc, al); @@ -1948,6 +2041,10 @@ BEGIN (* L: *) |IL.opINF: + INC(fr); + IF fr > MAX_FR THEN + ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR) + END; pushc(7FF00000H); pushc(0); OutByte3(0DDH, 004H, 024H); (* fld qword[esp] *) @@ -2076,6 +2173,9 @@ BEGIN OutIntByte(n); OutByte(param2) + |IL.opFNAME: + fname := cmd(IL.FNAMECMD).fname + |IL.opLOOP, IL.opENDLOOP: END; @@ -2084,8 +2184,8 @@ BEGIN END; ASSERT(R.pushed = 0); - ASSERT(R.top = -1) - + ASSERT(R.top = -1); + ASSERT(fr = -1) END translate; @@ -2094,9 +2194,9 @@ VAR reg1, entry, L, dcount: INTEGER; BEGIN - entry := NewLabel(); SetLabel(entry); + dcount := CHL.Length(IL.codes.data); IF target = TARGETS.Win32DLL THEN push(ebp); @@ -2106,19 +2206,17 @@ BEGIN pushm(ebp, 8); CallRTL(pic, IL._dllentry); test(eax); - jcc(je, dllret) + jcc(je, dllret); + pushc(0) ELSIF target = TARGETS.KolibriOSDLL THEN - SetLabel(dllinit) - END; - - IF target = TARGETS.KolibriOS THEN + SetLabel(dllinit); + OutByte(68H); (* push IMPORT *) + Reloc(BIN.IMPTAB, 0) + ELSIF target = TARGETS.KolibriOS THEN reg1 := GetAnyReg(); Pic(reg1, BIN.IMPTAB, 0); push(reg1); (* push IMPORT *) drop - ELSIF target = TARGETS.KolibriOSDLL THEN - OutByte(68H); (* push IMPORT *) - Reloc(BIN.IMPTAB, 0) ELSIF target = TARGETS.Linux32 THEN push(esp) ELSE @@ -2128,40 +2226,26 @@ BEGIN IF pic THEN reg1 := GetAnyReg(); Pic(reg1, BIN.PICCODE, entry); - push(reg1); (* push CODE *) - drop - ELSE - OutByte(68H); (* push CODE *) - Reloc(BIN.RCODE, entry) - END; - - IF pic THEN - reg1 := GetAnyReg(); + push(reg1); (* push CODE *) Pic(reg1, BIN.PICDATA, 0); push(reg1); (* push _data *) - drop - ELSE - OutByte(68H); (* push _data *) - Reloc(BIN.RDATA, 0) - END; - - dcount := CHL.Length(IL.codes.data); - - pushc(tcount); - - IF pic THEN - reg1 := GetAnyReg(); + pushc(tcount); Pic(reg1, BIN.PICDATA, tcount * 4 + dcount); push(reg1); (* push _data + tcount * 4 + dcount *) drop ELSE + OutByte(68H); (* push CODE *) + Reloc(BIN.RCODE, entry); OutByte(68H); (* push _data *) + Reloc(BIN.RDATA, 0); + pushc(tcount); + OutByte(68H); (* push _data + tcount * 4 + dcount *) Reloc(BIN.RDATA, tcount * 4 + dcount) END; CallRTL(pic, IL._init); - IF target = TARGETS.Linux32 THEN + IF target IN {TARGETS.Win32C, TARGETS.Win32GUI, TARGETS.Linux32} THEN L := NewLabel(); pushc(0); push(esp); @@ -2186,7 +2270,7 @@ VAR dcount, i: INTEGER; - PROCEDURE import (imp: LISTS.LIST); + PROCEDURE _import (imp: LISTS.LIST); VAR lib: IL.IMPORT_LIB; proc: IL.IMPORT_PROC; @@ -2204,7 +2288,7 @@ VAR lib := lib.next(IL.IMPORT_LIB) END - END import; + END _import; BEGIN @@ -2256,12 +2340,11 @@ BEGIN exp := exp.next(IL.EXPORT_PROC) END; - import(IL.codes.import); + _import(IL.codes._import); IL.set_bss(MAX(IL.codes.bss, MAX(IL.codes.dmin - CHL.Length(IL.codes.data), 4))); - BIN.SetParams(program, IL.codes.bss, stack * (1024 * 1024), WCHR(ver DIV 65536), WCHR(ver MOD 65536)); - + BIN.SetParams(program, IL.codes.bss, stack * (1024 * 1024), WCHR(ver DIV 65536), WCHR(ver MOD 65536)) END epilog; @@ -2271,6 +2354,7 @@ VAR opt: PROG.OPTIONS; BEGIN + FR[0] := 0; tcount := CHL.Length(IL.codes.types); opt := options; diff --git a/programs/develop/oberon07/doc/CC.txt b/programs/develop/oberon07/doc/CC.txt new file mode 100644 index 000000000..e54f67a65 --- /dev/null +++ b/programs/develop/oberon07/doc/CC.txt @@ -0,0 +1,36 @@ +Условная компиляция + +синтаксис: + + $IF "(" ident {"|" ident} ")" + <...> + {$ELSIF "(" ident {"|" ident} ")"} + <...> + [$ELSE] + <...> + $END + + где ident: + - одно из возможных значений параметра в командной строке + - пользовательский идентификатор, переданный с ключом -def при компиляции + +примеры: + + $IF (win64con | win64gui | win64dll) + OS := "WIN64"; + $ELSIF (win32con | win32gui | win32dll) + OS := "WIN32"; + $ELSIF (linux64exe | linux64so) + OS := "LINUX64"; + $ELSIF (linux32exe | linux32so) + OS := "LINUX32"; + $ELSE + OS := "UNKNOWN"; + $END + + + $IF (CPUX86_64) (* -def CPUX86_64 *) + bit_depth := 64; + $ELSE + bit_depth := 32; + $END diff --git a/programs/develop/oberon07/Docs/KOSLib.txt b/programs/develop/oberon07/doc/KOSLib.txt similarity index 100% rename from programs/develop/oberon07/Docs/KOSLib.txt rename to programs/develop/oberon07/doc/KOSLib.txt diff --git a/programs/develop/oberon07/doc/MSP430.txt b/programs/develop/oberon07/doc/MSP430.txt new file mode 100644 index 000000000..7bc92584c --- /dev/null +++ b/programs/develop/oberon07/doc/MSP430.txt @@ -0,0 +1,520 @@ + Компилятор языка программирования Oberon-07/16 для + микроконтроллеров MSP430x{1,2}xx. +------------------------------------------------------------------------------ + + Параметры командной строки + + Вход - текстовые файлы модулей с расширением ".ob07", кодировка ANSI или +UTF-8 с BOM-сигнатурой. + Выход - hex-файл прошивки. + Параметры: + 1) имя главного модуля + 2) "msp430" + 3) необязательные параметры-ключи + -out имя результирующего файла; по умолчанию, + совпадает с именем главного модуля, но с расширением ".hex" + -ram размер ОЗУ в байтах (128 - 2048) по умолчанию 128 + -rom размер ПЗУ в байтах (2048 - 24576) по умолчанию 2048 + -nochk <"ptibcwra"> отключить проверки при выполнении + -lower разрешить ключевые слова и встроенные идентификаторы в + нижнем регистре + -def <имя> задать символ условной компиляции + + параметр -nochk задается в виде строки из символов: + "p" - указатели + "t" - типы + "i" - индексы + "b" - неявное приведение INTEGER к BYTE + "c" - диапазон аргумента функции CHR + "a" - все проверки + + Порядок символов может быть любым. Наличие в строке того или иного + символа отключает соответствующую проверку. + + Например: -nochk it - отключить проверку индексов и охрану типа. + -nochk a - отключить все отключаемые проверки. + + Например: + + Compiler.exe "C:\example.ob07" msp430 -ram 128 -rom 4096 -nochk pti + Compiler.exe "C:\example.ob07" msp430 -out "C:\Ex1.hex" -ram 512 -rom 16384 + + В случае успешной компиляции, компилятор передает код завершения 0, иначе 1. +При работе компилятора в KolibriOS, код завершения не передается. + +------------------------------------------------------------------------------ + Отличия от оригинала + + 1. Расширен псевдомодуль SYSTEM + 2. В идентификаторах допускается символ "_" + 3. Усовершенствован оператор CASE (добавлены константные выражения в + метках вариантов и необязательная ветка ELSE) + 4. Расширен набор стандартных процедур + 5. Семантика охраны/проверки типа уточнена для нулевого указателя + 6. Добавлены однострочные комментарии (начинаются с пары символов "//") + 7. Разрешено наследование от типа-указателя + 8. "Строки" можно заключать также в одиночные кавычки: 'строка' + 9. Добавлена операция конкатенации строковых и символьных констант +10. Добавлены кодовые процедуры +11. Не реализована вещественная арифметика + +------------------------------------------------------------------------------ + Особенности реализации + +1. Основные типы + + Тип Диапазон значений Размер, байт + + INTEGER -32768 .. 32767 2 + CHAR символ ASCII (0X .. 0FFX) 1 + BOOLEAN FALSE, TRUE 1 + SET множество из целых чисел {0 .. 15} 2 + BYTE 0 .. 255 1 + +2. Максимальная длина идентификаторов - 1024 символов +3. Максимальная длина строковых констант - 1024 символов (UTF-8) +4. Максимальная размерность открытых массивов - 5 +5. Процедура NEW заполняет нулями выделенный блок памяти +6. Локальные переменные инициализируются нулями +7. В отличие от многих Oberon-реализаций, сборщик мусора и динамическая + модульность отсутствуют +8. Тип BYTE в выражениях всегда приводится к INTEGER +9. Контроль переполнения значений выражений не производится +10. Ошибки времени выполнения: + +номер ошибка + + 1 ASSERT(x), при x = FALSE + 2 разыменование нулевого указателя + 3 целочисленное деление на неположительное число + 4 вызов процедуры через процедурную переменную с нулевым значением + 5 ошибка охраны типа + 6 нарушение границ массива + 7 непредусмотренное значение выражения в операторе CASE + 8 ошибка копирования массивов v := x, если LEN(v) < LEN(x) + 9 CHR(x), если (x < 0) OR (x > 255) +11 неявное приведение x:INTEGER к v:BYTE, если (x < 0) OR (x > 255) + +------------------------------------------------------------------------------ + Псевдомодуль SYSTEM + + Псевдомодуль SYSTEM содержит низкоуровневые и небезопасные процедуры, +ошибки при использовании процедур псевдомодуля SYSTEM могут привести к +повреждению данных времени выполнения и аварийному завершению программы. + + PROCEDURE ADR(v: любой тип): INTEGER + v - переменная или процедура; + возвращает адрес v + + PROCEDURE SADR(x: строковая константа): INTEGER + возвращает адрес x + + PROCEDURE SIZE(T): INTEGER + возвращает размер типа T + + PROCEDURE TYPEID(T): INTEGER + T - тип-запись или тип-указатель, + возвращает номер типа в таблице типов-записей + + PROCEDURE MOVE(Source, Dest, n: INTEGER) + Копирует n байт памяти из Source в Dest, + области Source и Dest не могут перекрываться + + PROCEDURE GET(a: INTEGER; + VAR v: любой основной тип, PROCEDURE, POINTER) + v := Память[a] + + PROCEDURE GET8(a: INTEGER; VAR x: INTEGER, SET, BYTE, CHAR) + Эквивалентно + SYSTEM.MOVE(a, SYSTEM.ADR(x), 1) + + PROCEDURE PUT(a: INTEGER; x: любой основной тип, PROCEDURE, POINTER) + Память[a] := x; + Если x: BYTE, то значение x будет расширено до 16 бит, + для записи байтов использовать SYSTEM.PUT8 + + PROCEDURE PUT8(a: INTEGER; x: INTEGER, SET, BYTE, CHAR) + Память[a] := младшие 8 бит (x) + + PROCEDURE CODE(word1, word2,... : INTEGER) + Вставка машинного кода, + word1, word2 ... - целочисленные константы (константные + выражения) - машинные слова, например: + SYSTEM.CODE(0D032H, 0010H) (* BIS #16, SR; CPUOFF *) + + + Функции псевдомодуля SYSTEM нельзя использовать в константных выражениях. + +------------------------------------------------------------------------------ + Оператор CASE + + Синтаксис оператора CASE: + + CaseStatement = + CASE Expression OF Сase {"|" Сase} + [ELSE StatementSequence] END. + Case = [CaseLabelList ":" StatementSequence]. + CaseLabelList = CaseLabels {"," CaseLabels}. + CaseLabels = ConstExpression [".." ConstExpression]. + + Например: + + CASE x OF + |-1: DoSomething1 + | 1: DoSomething2 + | 0: DoSomething3 + ELSE + DoSomething4 + END + + В метках вариантов можно использовать константные выражения, ветка ELSE +необязательна. Если значение x не соответствует ни одному варианту и ELSE +отсутствует, то программа прерывается с ошибкой времени выполнения. + +------------------------------------------------------------------------------ + Конкатенация строковых и символьных констант + + Допускается конкатенация ("+") константных строк и символов типа CHAR: + + str = CHR(39) + "string" + CHR(39); (* str = "'string'" *) + + newline = 0DX + 0AX; + +------------------------------------------------------------------------------ + Проверка и охрана типа нулевого указателя + + Оригинальное сообщение о языке не определяет поведение программы при +выполнении охраны p(T) и проверки типа p IS T при p = NIL. Во многих +Oberon-реализациях выполнение такой операции приводит к ошибке времени +выполнения. В данной реализации охрана типа нулевого указателя не приводит к +ошибке, а проверка типа дает результат FALSE. В ряде случаев это позволяет +значительно сократить частоту применения охраны типа. + +------------------------------------------------------------------------------ + Дополнительные стандартные процедуры + + + COPY (x: ARRAY OF CHAR; VAR v: ARRAY OF CHAR); + v := x; + Если LEN(v) < LEN(x), то строка x будет скопирована + не полностью. + + LSR (x, n: INTEGER): INTEGER + Логический сдвиг x на n бит вправо. + + MIN (a, b: INTEGER): INTEGER + Минимум из двух значений. + + MAX (a, b: INTEGER): INTEGER + Максимум из двух значений. + + BITS (x: INTEGER): SET + Интерпретирует x как значение типа SET. + Выполняется на этапе компиляции. + + LENGTH (s: ARRAY OF CHAR): INTEGER + Длина 0X-завершенной строки s, без учета символа 0X. + Если символ 0X отсутствует, функция возвращает длину + массива s. s не может быть константой. + +------------------------------------------------------------------------------ + Использование регистров общего назначения R4 - R15 + + R4 - R7: регистровый стэк (промежуточные значения выражений) + R8 - R13: не используются + R14: указатель кучи + R15: используется при обработке прерываний + +------------------------------------------------------------------------------ + Вызов процедур и кадр стэка + + Правила вызова похожи на соглашение cdecl (x86): + - параметры передаются через стэк справа налево + - результат, если есть, передается через регистр R4 + - вызывающая процедура очищает стэк + + Состояние стэка при выполнении процедуры: + + меньшие адреса <- |var3|var2|var1|PC|arg1|arg2|arg3| -> бОльшие адреса + + PC - значение регистра PC перед вызовом (адрес возврата) + argX - параметры в порядке объявления (слева направо) + varX - локальные переменные в порядке использования в процедуре + + Размер каждого элемента в стэке (кроме локальных переменных структурных + типов) - 1 машинное слово (2 байта). Структурные переменные (массивы и + записи) занимают место в стэке в соответствии с их размером (с учетом + выравнивания). + + Размещение локальных переменных зависит от их размеров и порядка + использования, и в общем случае неопределенно. Если переменная не + используется явно, то компилятор не выделяет для нее место в стэке. + +------------------------------------------------------------------------------ + Скрытые параметры процедур + + Некоторые процедуры могут иметь скрытые параметры, они отсутствуют в списке +формальных параметров, но учитываются компилятором при трансляции вызовов. +Это возможно в следующих случаях: + +1. Процедура имеет формальный параметр открытый массив: + PROCEDURE Proc (x: ARRAY OF ARRAY OF REAL); + Вызов транслируется так: + Proc(LEN(x), LEN(x[0]), SYSTEM.ADR(x)) +2. Процедура имеет формальный параметр-переменную типа RECORD: + PROCEDURE Proc (VAR x: Rec); + Вызов транслируется так: + Proc(SYSTEM.TYPEID(Rec), SYSTEM.ADR(x)) + +------------------------------------------------------------------------------ + Кодовые процедуры + + Компилятор поддерживает процедуры, написаные в машинных кодах. + Синтаксис: + + PROCEDURE "[code]" имя [ (параметры): ТипРезультата ] + МашСлово, МашСлово,... МашСлово; + + ";" после заголовка и END "имя" в конце процедуры не ставятся. + МашСлово - целочисленная константа (в том числе и константное выражение). + Например: + + PROCEDURE [code] asr (n, x: INTEGER): INTEGER (* ASR(x, n) -> R4 *) + 4115H, 2, (* MOV 2(SP), R5; R5 <- n *) + 4114H, 4, (* MOV 4(SP), R4; R4 <- x *) + 0F035H, 15, (* AND #15, R5 *) + 2400H + 3, (* JZ L1 *) + (* L2: *) + 1104H, (* RRA R4 *) + 8315H, (* SUB #1, R5 *) + 2000H + 400H - 3; (* JNZ L2 *) + (* L1: *) + + Компилятор автоматически добавляет к такой процедуре команду RET. + Способ передачи параметров и результата не изменяется. + + Кодовые процедуры можно использовать также и для добавления в программу +константных данных: + + PROCEDURE [code] sqr + 0, 1, 4, 9, 16, 25, 36, 49, 64, 81; + + Получить адрес такой "процедуры": SYSTEM.ADR(sqr). + Получить адрес n-го машинного слова: SYSTEM.ADR(sqr) + n * 2. + + Чтобы использовать кодовые процедуры, необходимо импортировать псевдомодуль +SYSTEM. + +------------------------------------------------------------------------------ + Обработка прерываний + + При появлении запроса на прерывание, процессор: + - помещает в стэк значение регистра PC + - помещает в стэк значение регистра SR + - очищает регистр SR + - выполняет переход по адресу IV[priority], где + IV - таблица векторов прерываний, + priority - приоритет прерывания (номер элемента в таблице IV) (0..30) + + Компилятор генерирует код обработки прерываний: + + ; IV[0] = адрес следующей команды + PUSH #0 ; поместить в стэк приоритет прерывания + JMP Label ; перейти к обработчику + + ; IV[1] = адрес следующей команды + PUSH #1 ; поместить в стэк приоритет прерывания + JMP Label ; перейти к обработчику + + ... + ; IV[priority] = адрес следующей команды + PUSH #priority ; поместить в стэк приоритет прерывания + JMP Label ; перейти к обработчику + + ... + ; IV[30] = адрес следующей команды + PUSH #30 ; поместить в стэк приоритет прерывания + + Label: + MOV SP, R15 ; настроить R15 на структуру данных прерывания (см. далее) + PUSH R4 ; сохранить рабочие регистры (R4 - R7) + ... + PUSH R7 + PUSH R15 ; передать параметр interrupt в обработчик (см. далее) + PUSH @R15 ; передать параметр priority в обработчик (см. далее) + CALL int ; вызвать обработчик (см. далее) + ADD #4, SP ; удалить из стэка параметры обработчика + POP R7 ; восстановить рабочие регистры (R7 - R4) + ... + POP R4 + ADD #2, SP ; удалить из стэка значение priority + RETI ; возврат из прерывания (восстановить SR и PC) + +------------------------------------------------------------------------------ + Обработка ошибок + + В случае возникновения ошибки при выполнении программы, будет вызван общий +обработчик ошибок, который: + + - запрещает прерывания + - сбрасывает стэк (во избежание переполнения в процессе обработки ошибки) + - передает параметры в пользовательский обработчик (см. далее) + - вызывает пользовательский обработчик (если он назначен) + - повторно запрещает прерывания + - выключает CPU и все тактовые сигналы + + Если выключать CPU не требуется, то пользовательский обработчик может, +например, перезапустить программу. + +------------------------------------------------------------------------------ + Инициализация и финализация программы + + В начало программы компилятор вставляет код, который: + - инициализирует регистры SP и R14 + - выключает сторожевой таймер + - назначает пустой обработчик прерываний + - сбрасывает обработчик ошибок + + В конец программы добавляет команду + BIS #16, SR; выключить CPU + +------------------------------------------------------------------------------ + Структура ОЗУ (RAM) + + начало -> | спец. переменные | глобальные переменные | куча/стэк | <- конец + + Компилятор поддерживает размер ОЗУ 128..2048 байт. В нижних адресах +располагаются специальные переменные, и далее пользовательские глобальные +переменные. Оставшаяся часть памяти отводится для кучи и стэка (не менее 64 +байта). При старте программы, в регистр R14 записывается адрес начала области +кучи/стэка, а регистр SP настраивается на конец ОЗУ (начало_ОЗУ + размер_ОЗУ). +При выделении памяти процедурой NEW, значение регистра R14 увеличивается (если +есть свободная память). Таким образом, стэк и куча растут навстречу друг +другу. Проверка переполнения стэка не производится. + +------------------------------------------------------------------------------ + Структура ПЗУ (RОM) + + начало -> |код|свободная область|спец. данные|векторы прерываний| <- конец + + Компилятор поддерживает размер ПЗУ 2048..24576 байт. В верхних адресах +располагается таблица векторов прерываний (64 байта), адреса 0FFC0H..0FFFFH. +Непосредственно перед ней размещаются специальные данные. Программный +код начинается с адреса (10000H - размер_ПЗУ), этот адрес является также и +точкой входа в программу. Между кодом и спец. данными может оставаться +свободное пространство. Если размер ПЗУ больше, чем указан при компиляции, +то перед кодом будет свободная область. Таким способом можно зарезервировать +нижние сегменты флэш-памяти для записи во время выполнения программы. + +============================================================================== +MODULE MSP430 + +CONST + + биты регистра SR: + + GIE = {3} + CPUOFF = {4} + OSCOFF = {5} + SCG0 = {6} + SCG1 = {7} + + +TYPE + + TInterrupt = RECORD priority: INTEGER; sr: SET; pc: INTEGER END + структура данных прерывания + + priority - приоритет прерывания: + + адрес приоритет + 0FFFEH 31 + 0FFFCH 30 + 0FFFAH 29 + ... + 0FFC0H 0 + + sr - сохраненное значение регистра SR + pc - сохраненное значение регистра PC + + + TTrapProc = PROCEDURE (modNum, modName, err, line: INTEGER); + Процедура-обработчик ошибок. + + modNum - номер модуля (в отчете о компиляции: + compiling (modNum) "modName" ) + modName - адрес имени модуля + err - номер ошибки + line - номер строки + + + TIntProc = PROCEDURE (priority: INTEGER; interrupt: TInterrupt) + Процедура-обработчик прерываний. + + priority - приоритет прерывания + interrupt - структура данных прерывания + + + PROCEDURE SetTrapProc (TrapProc: TTrapProc) + Назначить обработчик ошибок. + + + PROCEDURE SetIntProc (IntProc: TIntProc) + Назначить обработчик прерываний. + + Нельзя вызывать эту процедуру с параметром NIL, т. к. для экономии + тактов, значение адреса обработчика прерываний не проверяется на NIL. + + + PROCEDURE Restart + Перезапустить программу. + При этом: очищается регистр SR, повторно выполняется код инициализации + программы (см. выше). Всё прочее состояние ОЗУ и регистров устройств + сохраняется. + + + PROCEDURE SetIntPC (interrupt: TInterrupt; NewPC: INTEGER) + interrupt.pc := NewPC + После возврата из прерывания, регистр PC получит значение NewPC. + + + PROCEDURE SetIntSR (interrupt: TInterrupt; NewSR: SET) + interrupt.sr := NewSR + После возврата из прерывания, регистр SR получит значение NewSR. + + + PROCEDURE DInt + Запретить прерывания. + + + PROCEDURE EInt + Разрешить прерывания. + + + PROCEDURE CpuOff + Выключить CPU (установить бит CPUOFF регистра SR). + + + PROCEDURE Halt + Запретить прерывания, выключить CPU и все тактовые сигналы. + + + PROCEDURE SetSR (bits: SET) + Установить биты bits регистра SR. + + + PROCEDURE ClrSR (bits: SET) + Сбросить биты bits регистра SR. + + + PROCEDURE GetFreeFlash (VAR address, size: INTEGER) + Получить адрес и размер свободной области Flash/ROM + (между кодом и данными). + + + PROCEDURE Delay (n: INTEGER) + Задержка выполнения программы на 1000*n тактов, + но не менее чем на 2000 тактов. + + +============================================================================== \ No newline at end of file diff --git a/programs/develop/oberon07/Docs/Oberon07.Report_2016_05_03.pdf b/programs/develop/oberon07/doc/Oberon07.Report_2016_05_03.pdf similarity index 100% rename from programs/develop/oberon07/Docs/Oberon07.Report_2016_05_03.pdf rename to programs/develop/oberon07/doc/Oberon07.Report_2016_05_03.pdf diff --git a/programs/develop/oberon07/doc/STM32.txt b/programs/develop/oberon07/doc/STM32.txt new file mode 100644 index 000000000..8b3e9a3aa --- /dev/null +++ b/programs/develop/oberon07/doc/STM32.txt @@ -0,0 +1,404 @@ + Компилятор языка программирования Oberon-07/16 для + микроконтроллеров STM32 Cortex-M3. + +------------------------------------------------------------------------------ + Параметры командной строки + + Вход - текстовые файлы модулей с расширением ".ob07", кодировка ANSI или +UTF-8 с BOM-сигнатурой. + Выход - hex-файл прошивки. + Параметры: + 1) имя главного модуля + 2) "stm32cm3" + 3) необязательные параметры-ключи + -out имя результирующего файла; по умолчанию, + совпадает с именем главного модуля, но с расширением ".hex" + -ram размер ОЗУ в килобайтах (4 - 65536) по умолчанию 4 + -rom размер ПЗУ в килобайтах (16 - 65536) по умолчанию 16 + -nochk <"ptibcwra"> отключить проверки при выполнении + -lower разрешить ключевые слова и встроенные идентификаторы в + нижнем регистре + -def <имя> задать символ условной компиляции + + параметр -nochk задается в виде строки из символов: + "p" - указатели + "t" - типы + "i" - индексы + "b" - неявное приведение INTEGER к BYTE + "c" - диапазон аргумента функции CHR + "w" - диапазон аргумента функции WCHR + "r" - эквивалентно "bcw" + "a" - все проверки + + Порядок символов может быть любым. Наличие в строке того или иного + символа отключает соответствующую проверку. + + Например: -nochk it - отключить проверку индексов и охрану типа. + -nochk a - отключить все отключаемые проверки. + + Например: + + Compiler.exe "C:\example.ob07" stm32cm3 -ram 32 -rom 256 -nochk pti + Compiler.exe "C:\example.ob07" stm32cm3 -out "C:\Ex1.hex" -ram 8 -rom 32 + + В случае успешной компиляции, компилятор передает код завершения 0, иначе 1. +При работе компилятора в KolibriOS, код завершения не передается. + +------------------------------------------------------------------------------ + Отличия от оригинала + + 1. Расширен псевдомодуль SYSTEM + 2. В идентификаторах допускается символ "_" + 3. Усовершенствован оператор CASE (добавлены константные выражения в + метках вариантов и необязательная ветка ELSE) + 4. Расширен набор стандартных процедур + 5. Семантика охраны/проверки типа уточнена для нулевого указателя + 6. Добавлены однострочные комментарии (начинаются с пары символов "//") + 7. Разрешено наследование от типа-указателя + 8. "Строки" можно заключать также в одиночные кавычки: 'строка' + 9. Добавлен тип WCHAR +10. Добавлена операция конкатенации строковых и символьных констант +11. Добавлены кодовые процедуры + +------------------------------------------------------------------------------ + Особенности реализации + +1. Основные типы + + Тип Диапазон значений Размер, байт + + INTEGER -2147483648 .. 2147483647 4 + REAL 1.17E-38 .. 3.40E+38 4 + CHAR символ ASCII (0X .. 0FFX) 1 + BOOLEAN FALSE, TRUE 1 + SET множество из целых чисел {0 .. 31} 4 + BYTE 0 .. 255 1 + WCHAR символ юникода (0X .. 0FFFFX) 2 + +2. Максимальная длина идентификаторов - 1024 символов +3. Максимальная длина строковых констант - 1024 символов (UTF-8) +4. Максимальная размерность открытых массивов - 5 +5. Процедура NEW заполняет нулями выделенный блок памяти +6. Локальные переменные инициализируются нулями +7. В отличие от многих Oberon-реализаций, сборщик мусора и динамическая + модульность отсутствуют +8. Тип BYTE в выражениях всегда приводится к INTEGER +9. Контроль переполнения значений выражений не производится + +------------------------------------------------------------------------------ + Псевдомодуль SYSTEM + + Псевдомодуль SYSTEM содержит низкоуровневые и небезопасные процедуры, +ошибки при использовании процедур псевдомодуля SYSTEM могут привести к +повреждению данных времени выполнения и аварийному завершению программы. + + PROCEDURE ADR(v: любой тип): INTEGER + v - переменная или процедура; + возвращает адрес v + + PROCEDURE SADR(x: строковая константа (CHAR UTF-8)): INTEGER + возвращает адрес x + + PROCEDURE WSADR(x: строковая константа (WCHAR)): INTEGER + возвращает адрес x + + PROCEDURE SIZE(T): INTEGER + возвращает размер типа T + + PROCEDURE TYPEID(T): INTEGER + T - тип-запись или тип-указатель, + возвращает номер типа в таблице типов-записей + + PROCEDURE INF(): REAL + возвращает специальное вещественное значение "бесконечность" + + PROCEDURE MOVE(Source, Dest, n: INTEGER) + Копирует n байт памяти из Source в Dest, + области Source и Dest не могут перекрываться + + PROCEDURE GET(a: INTEGER; + VAR v: любой основной тип, PROCEDURE, POINTER) + v := Память[a] + + PROCEDURE GET8(a: INTEGER; + VAR x: INTEGER, SET, BYTE, CHAR, WCHAR, SYSTEM.CARD32) + Эквивалентно + SYSTEM.MOVE(a, SYSTEM.ADR(x), 1) + + PROCEDURE GET16(a: INTEGER; + VAR x: INTEGER, SET, WCHAR, SYSTEM.CARD32) + Эквивалентно + SYSTEM.MOVE(a, SYSTEM.ADR(x), 2) + + PROCEDURE GET32(a: INTEGER; VAR x: INTEGER, SET, SYSTEM.CARD32) + Эквивалентно + SYSTEM.MOVE(a, SYSTEM.ADR(x), 4) + + PROCEDURE PUT(a: INTEGER; x: любой основной тип, PROCEDURE, POINTER) + Память[a] := x; + Если x: BYTE или x: WCHAR, то значение x будет расширено + до 32 бит, для записи байтов использовать SYSTEM.PUT8, + для WCHAR -- SYSTEM.PUT16 + + PROCEDURE PUT8(a: INTEGER; + x: INTEGER, SET, BYTE, CHAR, WCHAR, SYSTEM.CARD32) + Память[a] := младшие 8 бит (x) + + PROCEDURE PUT16(a: INTEGER; + x: INTEGER, SET, BYTE, CHAR, WCHAR, SYSTEM.CARD32) + Память[a] := младшие 16 бит (x) + + PROCEDURE PUT32(a: INTEGER; + x: INTEGER, SET, BYTE, CHAR, WCHAR, SYSTEM.CARD32) + Память[a] := младшие 32 бит (x) + + PROCEDURE CODE(hword1, hword2,... : INTEGER) + Вставка машинного кода, + hword1, hword2 ... - константы в диапазоне 0..65535, + например: + SYSTEM.CODE(0BF30H) (* wfi *) + + Также, в модуле SYSTEM определен тип CARD32 (4 байта). Для типа CARD32 не +допускаются никакие явные операции, за исключением присваивания. + + Функции псевдомодуля SYSTEM нельзя использовать в константных выражениях. + +------------------------------------------------------------------------------ + Оператор CASE + + Синтаксис оператора CASE: + + CaseStatement = + CASE Expression OF Сase {"|" Сase} + [ELSE StatementSequence] END. + Case = [CaseLabelList ":" StatementSequence]. + CaseLabelList = CaseLabels {"," CaseLabels}. + CaseLabels = ConstExpression [".." ConstExpression]. + + Например: + + CASE x OF + |-1: DoSomething1 + | 1: DoSomething2 + | 0: DoSomething3 + ELSE + DoSomething4 + END + + В метках вариантов можно использовать константные выражения, ветка ELSE +необязательна. Если значение x не соответствует ни одному варианту и ELSE +отсутствует, то программа прерывается с ошибкой времени выполнения. + +------------------------------------------------------------------------------ + Тип WCHAR + + Тип WCHAR добавлен в язык для удобной поддежки юникода. Для типов WCHAR и +ARRAY OF WCHAR допускаются все те же операции, как для типов CHAR и +ARRAY OF CHAR, за исключением встроенной процедуры CHR, которая возвращает +только тип CHAR. Для получения значения типа WCHAR, следует использовать +процедуру WCHR вместо CHR. Для правильной работы с типом, необходимо сохранять +исходный код в кодировке UTF-8 c BOM. + +------------------------------------------------------------------------------ + Конкатенация строковых и символьных констант + + Допускается конкатенация ("+") константных строк и символов типа CHAR: + + str = CHR(39) + "string" + CHR(39); (* str = "'string'" *) + + newline = 0DX + 0AX; + +------------------------------------------------------------------------------ + Проверка и охрана типа нулевого указателя + + Оригинальное сообщение о языке не определяет поведение программы при +выполнении охраны p(T) и проверки типа p IS T при p = NIL. Во многих +Oberon-реализациях выполнение такой операции приводит к ошибке времени +выполнения. В данной реализации охрана типа нулевого указателя не приводит к +ошибке, а проверка типа дает результат FALSE. В ряде случаев это позволяет +значительно сократить частоту применения охраны типа. + +------------------------------------------------------------------------------ + Дополнительные стандартные процедуры + + + COPY (x: ARRAY OF CHAR/WCHAR; VAR v: ARRAY OF CHAR/WCHAR); + v := x; + Если LEN(v) < LEN(x), то строка x будет скопирована + не полностью + + LSR (x, n: INTEGER): INTEGER + Логический сдвиг x на n бит вправо. + + MIN (a, b: INTEGER): INTEGER + Минимум из двух значений. + + MAX (a, b: INTEGER): INTEGER + Максимум из двух значений. + + BITS (x: INTEGER): SET + Интерпретирует x как значение типа SET. + Выполняется на этапе компиляции. + + LENGTH (s: ARRAY OF CHAR/WCHAR): INTEGER + Длина 0X-завершенной строки s, без учета символа 0X. + Если символ 0X отсутствует, функция возвращает длину + массива s. s не может быть константой. + + WCHR (n: INTEGER): WCHAR + Преобразование типа, аналогично CHR(n: INTEGER): CHAR + +------------------------------------------------------------------------------ + Использование регистров общего назначения R0 - R12 + + R0 - R3: регистровый стэк (промежуточные значения выражений) + R4 - R12: не используются + +------------------------------------------------------------------------------ + Вызов процедур и кадр стэка + + Правила вызова похожи на соглашение cdecl (x86): + - параметры передаются через стэк справа налево + - результат, если есть, передается через регистр R0 + - вызывающая процедура очищает стэк + + Состояние стэка при выполнении процедуры: + + меньшие адреса <- |var3|var2|var1|LR|arg1|arg2|arg3| -> бОльшие адреса + + LR - сохраненный регистр LR (адрес возврата) + argX - параметры в порядке объявления (слева направо) + varX - локальные переменные в порядке использования в процедуре + + Размер каждого элемента в стэке (кроме локальных переменных структурных + типов) - 1 машинное слово (4 байта). Структурные переменные (массивы и + записи) занимают место в стэке в соответствии с их размером (с учетом + выравнивания). + + Размещение локальных переменных зависит от их размеров и порядка + использования, и в общем случае неопределенно. Если переменная не + используется явно, то компилятор не выделяет для нее место в стэке. + +------------------------------------------------------------------------------ + Скрытые параметры процедур + + Некоторые процедуры могут иметь скрытые параметры, они отсутствуют в списке +формальных параметров, но учитываются компилятором при трансляции вызовов. +Это возможно в следующих случаях: + +1. Процедура имеет формальный параметр открытый массив: + PROCEDURE Proc (x: ARRAY OF ARRAY OF REAL); + Вызов транслируется так: + Proc(LEN(x), LEN(x[0]), SYSTEM.ADR(x)) +2. Процедура имеет формальный параметр-переменную типа RECORD: + PROCEDURE Proc (VAR x: Rec); + Вызов транслируется так: + Proc(SYSTEM.TYPEID(Rec), SYSTEM.ADR(x)) + +------------------------------------------------------------------------------ + Кодовые процедуры + + Компилятор поддерживает процедуры, написаные в машинных кодах. + Синтаксис: + + PROCEDURE "[code]" имя [ (параметры): ТипРезультата ] + МашКом, МашКом,... МашКом; + + ";" после заголовка и END "имя" в конце процедуры не ставятся. + МашКом - целочисленная константа [0..65535] (в том числе и константное + выражение). + + Например: + + PROCEDURE [code] WFI + 0BF30H; (* wfi *) + + Компилятор автоматически добавляет к такой процедуре команду возврата +(bx LR). Способ передачи параметров и результата не изменяется. Регистр LR, +при входе в процедуру не сохраняется. + + Чтобы использовать кодовые процедуры, необходимо импортировать псевдомодуль +SYSTEM. + +------------------------------------------------------------------------------ + Обработка прерываний + + При возникновении прерывания, будет вызван обработчик (если он объявлен). +Объявление обработчика: + + PROCEDURE handler_name [iv]; (* процедура без параметров *) + +iv - целочисленная константа (константное выражение), номер вектора прерывания +в таблице векторов, iv >= 2: + + 0 начальное значение SP + 1 сброс + ... + 15 SysTick + ... + 59 TIM6 + 60 TIM7 + ... + +например: + + (* обработчик прерываний от TIM6 *) + PROCEDURE tim6 [59]; + BEGIN + (* код обработки *) + END tim6; + + Также, можно объявить общий обработчик (iv = 0), который будет вызван, если +не назначен индивидуальный. Общий обработчик получает параметр - номер вектора +прерывания. По значению этого параметра, обработчик должен определить источник +прерывания и выполнить соответствующие действия: + + PROCEDURE handler (iv: INTEGER) [0]; + BEGIN + IF iv = 59 THEN + (* TIM6 *) + ELSIF iv = 60 THEN + (* TIM7 *) + ELSIF .... + .... + END + END handler; + +В конец программы компилятор добавляет команду ожидания прерывания. + +------------------------------------------------------------------------------ + Обработка ошибок + + В случае возникновения ошибки при выполнении программы, будет вызван +пользовательский обработчик (если он объявлен). + +Объявление обработчика ошибок: + + PROCEDURE trap (modNum, modName, err, line: INTEGER) [1]; + BEGIN + END trap; + + где, + modNum - номер модуля (в отчете о компиляции: + compiling (modNum) "modName" ) + modName - адрес имени модуля + err - код ошибки + line - номер строки + +Коды ошибок: + + 1 ASSERT(x), при x = FALSE + 2 разыменование нулевого указателя + 3 целочисленное деление на неположительное число + 4 вызов процедуры через процедурную переменную с нулевым значением + 5 ошибка охраны типа + 6 нарушение границ массива + 7 непредусмотренное значение выражения в операторе CASE + 8 ошибка копирования массивов v := x, если LEN(v) < LEN(x) + 9 CHR(x), если (x < 0) OR (x > 255) +10 WCHR(x), если (x < 0) OR (x > 65535) +11 неявное приведение x:INTEGER к v:BYTE, если (x < 0) OR (x > 255) + +После возврата из обработчика программа будет перезапущена. + +------------------------------------------------------------------------------ \ No newline at end of file diff --git a/programs/develop/oberon07/Docs/WinLib.txt b/programs/develop/oberon07/doc/WinLib.txt similarity index 100% rename from programs/develop/oberon07/Docs/WinLib.txt rename to programs/develop/oberon07/doc/WinLib.txt diff --git a/programs/develop/oberon07/Docs/x86.txt b/programs/develop/oberon07/doc/x86.txt similarity index 86% rename from programs/develop/oberon07/Docs/x86.txt rename to programs/develop/oberon07/doc/x86.txt index e26976fda..fe68fdf10 100644 --- a/programs/develop/oberon07/Docs/x86.txt +++ b/programs/develop/oberon07/doc/x86.txt @@ -25,6 +25,9 @@ UTF-8 с BOM-сигнатурой. -stk размер стэка в мегабайтах (по умолчанию 2 Мб, допустимо от 1 до 32 Мб) -nochk <"ptibcwra"> отключить проверки при выполнении (см. ниже) + -lower разрешить ключевые слова и встроенные идентификаторы в + нижнем регистре + -def <имя> задать символ условной компиляции -ver версия программы (только для kosdll) параметр -nochk задается в виде строки из символов: @@ -71,6 +74,7 @@ UTF-8 с BOM-сигнатурой. 9. Добавлен синтаксис для импорта процедур из внешних библиотек 10. "Строки" можно заключать также в одиночные кавычки: 'строка' 11. Добавлен тип WCHAR +12. Добавлена операция конкатенации строковых и символьных констант ------------------------------------------------------------------------------ Особенности реализации @@ -137,25 +141,45 @@ UTF-8 с BOM-сигнатурой. PROCEDURE INF(): REAL возвращает специальное вещественное значение "бесконечность" + PROCEDURE MOVE(Source, Dest, n: INTEGER) + Копирует n байт памяти из Source в Dest, + области Source и Dest не могут перекрываться + PROCEDURE GET(a: INTEGER; VAR v: любой основной тип, PROCEDURE, POINTER) v := Память[a] + PROCEDURE GET8(a: INTEGER; + VAR x: INTEGER, SET, BYTE, CHAR, WCHAR, SYSTEM.CARD32) + Эквивалентно + SYSTEM.MOVE(a, SYSTEM.ADR(x), 1) + + PROCEDURE GET16(a: INTEGER; + VAR x: INTEGER, SET, WCHAR, SYSTEM.CARD32) + Эквивалентно + SYSTEM.MOVE(a, SYSTEM.ADR(x), 2) + + PROCEDURE GET32(a: INTEGER; VAR x: INTEGER, SET, SYSTEM.CARD32) + Эквивалентно + SYSTEM.MOVE(a, SYSTEM.ADR(x), 4) + PROCEDURE PUT(a: INTEGER; x: любой основной тип, PROCEDURE, POINTER) Память[a] := x; Если x: BYTE или x: WCHAR, то значение x будет расширено до 32 бит, для записи байтов использовать SYSTEM.PUT8, для WCHAR -- SYSTEM.PUT16 - PROCEDURE PUT8(a: INTEGER; x: INTEGER, SET, BYTE, CHAR, WCHAR) + PROCEDURE PUT8(a: INTEGER; + x: INTEGER, SET, BYTE, CHAR, WCHAR, SYSTEM.CARD32) Память[a] := младшие 8 бит (x) - PROCEDURE PUT16(a: INTEGER; x: INTEGER, SET, BYTE, CHAR, WCHAR) + PROCEDURE PUT16(a: INTEGER; + x: INTEGER, SET, BYTE, CHAR, WCHAR, SYSTEM.CARD32) Память[a] := младшие 16 бит (x) - PROCEDURE MOVE(Source, Dest, n: INTEGER) - Копирует n байт памяти из Source в Dest, - области Source и Dest не могут перекрываться + PROCEDURE PUT32(a: INTEGER; + x: INTEGER, SET, BYTE, CHAR, WCHAR, SYSTEM.CARD32) + Память[a] := младшие 32 бит (x) PROCEDURE COPY(VAR Source: любой тип; VAR Dest: любой тип; n: INTEGER) Копирует n байт памяти из Source в Dest. @@ -168,6 +192,8 @@ UTF-8 с BOM-сигнатурой. например: SYSTEM.CODE(08BH, 045H, 008H) (* mov eax, dword [ebp + 08h] *) + Также, в модуле SYSTEM определен тип CARD32 (4 байта). Для типа CARD32 не +допускаются никакие явные операции, за исключением присваивания. Функции псевдомодуля SYSTEM нельзя использовать в константных выражениях. @@ -176,7 +202,7 @@ UTF-8 с BOM-сигнатурой. При объявлении процедурных типов и глобальных процедур, после ключевого слова PROCEDURE может быть указан флаг соглашения о вызове: [stdcall], -[ccall], [ccall16], [windows], [linux]. Например: +[ccall], [ccall16], [windows], [linux], [oberon]. Например: PROCEDURE [ccall] MyProc (x, y, z: INTEGER): INTEGER; @@ -185,6 +211,8 @@ UTF-8 с BOM-сигнатурой. Флаг [windows] - синоним для [stdcall], [linux] - синоним для [ccall16]. Знак "-" после имени флага ([stdcall-], [linux-], ...) означает, что результат процедуры можно игнорировать (не допускается для типа REAL). + Если флаг не указан или указан флаг [oberon], то принимается внутреннее +соглашение о вызове. При объявлении типов-записей, после ключевого слова RECORD может быть указан флаг [noalign]. Флаг [noalign] означает отсутствие выравнивания полей @@ -228,6 +256,15 @@ ARRAY OF CHAR, за исключением встроенной процедур процедуру WCHR вместо CHR. Для правильной работы с типом, необходимо сохранять исходный код в кодировке UTF-8 c BOM. +------------------------------------------------------------------------------ + Конкатенация строковых и символьных констант + + Допускается конкатенация ("+") константных строк и символов типа CHAR: + + str = CHR(39) + "string" + CHR(39); (* str = "'string'" *) + + newline = 0DX + 0AX; + ------------------------------------------------------------------------------ Проверка и охрана типа нулевого указателя @@ -277,15 +314,16 @@ Oberon-реализациях выполнение такой операции Синтаксис импорта: - PROCEDURE [callconv, "library", "function"] proc_name (FormalParam): Type; + PROCEDURE [callconv, library, function] proc_name (FormalParam): Type; - callconv -- соглашение о вызове - - "library" -- имя файла динамической библиотеки - - "function" -- имя импортируемой процедуры + - library -- имя файла динамической библиотеки (строковая константа) + - function -- имя импортируемой процедуры (строковая константа), если + указана пустая строка, то имя процедуры = proc_name например: - PROCEDURE [windows, "kernel32.dll", "ExitProcess"] exit (code: INTEGER); + PROCEDURE [windows, "kernel32.dll", ""] ExitProcess (code: INTEGER); PROCEDURE [stdcall, "Console.obj", "con_exit"] exit (bCloseWindow: BOOLEAN); @@ -327,6 +365,8 @@ Oberon-реализациях выполнение такой операции Вызов транслируется так: Proc(SYSTEM.TYPEID(Rec), SYSTEM.ADR(x)) + Скрытые параметры необходимо учитывать при связи с внешними приложениями. + ------------------------------------------------------------------------------ Модуль RTL @@ -349,8 +389,11 @@ Oberon-реализациях выполнение такой операции Разрешается экспортировать только процедуры. Для этого, процедура должна находиться в главном модуле программы, и ее имя должно быть отмечено символом -экспорта ("*"). KolibriOS DLL всегда экспортируют идентификаторы "version" -(версия программы) и "lib_init" - адрес процедуры инициализации DLL: +экспорта ("*"). Нельзя экспортировать процедуры, которые импортированы из +других dll-библиотек. + + KolibriOS DLL всегда экспортируют идентификаторы "version" (версия +программы) и "lib_init" - адрес процедуры инициализации DLL: PROCEDURE [stdcall] lib_init (): INTEGER diff --git a/programs/develop/oberon07/Docs/x86_64.txt b/programs/develop/oberon07/doc/x86_64.txt similarity index 86% rename from programs/develop/oberon07/Docs/x86_64.txt rename to programs/develop/oberon07/doc/x86_64.txt index 9655412ac..4e3a4e7d8 100644 --- a/programs/develop/oberon07/Docs/x86_64.txt +++ b/programs/develop/oberon07/doc/x86_64.txt @@ -23,6 +23,9 @@ UTF-8 с BOM-сигнатурой. -stk размер стэка в мегабайтах (по умолчанию 2 Мб, допустимо от 1 до 32 Мб) -nochk <"ptibcwra"> отключить проверки при выполнении + -lower разрешить ключевые слова и встроенные идентификаторы в + нижнем регистре + -def <имя> задать символ условной компиляции параметр -nochk задается в виде строки из символов: "p" - указатели @@ -63,6 +66,7 @@ UTF-8 с BOM-сигнатурой. 9. Добавлен синтаксис для импорта процедур из внешних библиотек 10. "Строки" можно заключать также в одиночные кавычки: 'строка' 11. Добавлен тип WCHAR +12. Добавлена операция конкатенации строковых и символьных констант ------------------------------------------------------------------------------ Особенности реализации @@ -129,29 +133,46 @@ UTF-8 с BOM-сигнатурой. PROCEDURE INF(): REAL возвращает специальное вещественное значение "бесконечность" + PROCEDURE MOVE(Source, Dest, n: INTEGER) + Копирует n байт памяти из Source в Dest, + области Source и Dest не могут перекрываться + PROCEDURE GET(a: INTEGER; VAR v: любой основной тип, PROCEDURE, POINTER) v := Память[a] + PROCEDURE GET8(a: INTEGER; + VAR x: INTEGER, SET, BYTE, CHAR, WCHAR, SYSTEM.CARD32) + Эквивалентно + SYSTEM.MOVE(a, SYSTEM.ADR(x), 1) + + PROCEDURE GET16(a: INTEGER; + VAR x: INTEGER, SET, WCHAR, SYSTEM.CARD32) + Эквивалентно + SYSTEM.MOVE(a, SYSTEM.ADR(x), 2) + + PROCEDURE GET32(a: INTEGER; VAR x: INTEGER, SET, SYSTEM.CARD32) + Эквивалентно + SYSTEM.MOVE(a, SYSTEM.ADR(x), 4) + PROCEDURE PUT(a: INTEGER; x: любой основной тип, PROCEDURE, POINTER) Память[a] := x; Если x: BYTE или x: WCHAR, то значение x будет расширено до 64 бит, для записи байтов использовать SYSTEM.PUT8, для WCHAR -- SYSTEM.PUT16 - PROCEDURE PUT8(a: INTEGER; x: INTEGER, SET, BYTE, CHAR, WCHAR) + PROCEDURE PUT8(a: INTEGER; + x: INTEGER, SET, BYTE, CHAR, WCHAR, SYSTEM.CARD32) Память[a] := младшие 8 бит (x) - PROCEDURE PUT16(a: INTEGER; x: INTEGER, SET, BYTE, CHAR, WCHAR) + PROCEDURE PUT16(a: INTEGER; + x: INTEGER, SET, BYTE, CHAR, WCHAR, SYSTEM.CARD32) Память[a] := младшие 16 бит (x) - PROCEDURE PUT32(a: INTEGER; x: INTEGER, SET, BYTE, CHAR, WCHAR) + PROCEDURE PUT32(a: INTEGER; + x: INTEGER, SET, BYTE, CHAR, WCHAR, SYSTEM.CARD32) Память[a] := младшие 32 бит (x) - PROCEDURE MOVE(Source, Dest, n: INTEGER) - Копирует n байт памяти из Source в Dest, - области Source и Dest не могут перекрываться - PROCEDURE COPY(VAR Source: любой тип; VAR Dest: любой тип; n: INTEGER) Копирует n байт памяти из Source в Dest. Эквивалентно @@ -173,8 +194,8 @@ UTF-8 с BOM-сигнатурой. Системные флаги При объявлении процедурных типов и глобальных процедур, после ключевого -слова PROCEDURE может быть указан флаг соглашения о вызове: [win64], [systemv], -[windows], [linux]. +слова PROCEDURE может быть указан флаг соглашения о вызове: +[win64], [systemv], [windows], [linux], [oberon]. Например: PROCEDURE [win64] MyProc (x, y, z: INTEGER): INTEGER; @@ -182,9 +203,9 @@ UTF-8 с BOM-сигнатурой. Флаг [windows] - синоним для [win64], [linux] - синоним для [systemv]. Знак "-" после имени флага ([win64-], [linux-], ...) означает, что результат процедуры можно игнорировать (не допускается для типа REAL). - Если флаг не указан, то принимается внутреннее соглашение о вызове. -[win64] и [systemv] используются для связи с операционной системой и внешними -приложениями. + Если флаг не указан или указан флаг [oberon], то принимается внутреннее +соглашение о вызове. [win64] и [systemv] используются для связи с +операционной системой и внешними приложениями. При объявлении типов-записей, после ключевого слова RECORD может быть указан флаг [noalign]. Флаг [noalign] означает отсутствие выравнивания полей @@ -228,6 +249,15 @@ ARRAY OF CHAR, за исключением встроенной процедур процедуру WCHR вместо CHR. Для правильной работы с типом, необходимо сохранять исходный код в кодировке UTF-8 c BOM. +------------------------------------------------------------------------------ + Конкатенация строковых и символьных констант + + Допускается конкатенация ("+") константных строк и символов типа CHAR: + + str = CHR(39) + "string" + CHR(39); (* str = "'string'" *) + + newline = 0DX + 0AX; + ------------------------------------------------------------------------------ Проверка и охрана типа нулевого указателя @@ -277,16 +307,18 @@ Oberon-реализациях выполнение такой операции Синтаксис импорта: - PROCEDURE [callconv, "library", "function"] proc_name (FormalParam): Type; + PROCEDURE [callconv, library, function] proc_name (FormalParam): Type; - callconv -- соглашение о вызове - - "library" -- имя файла динамической библиотеки - - "function" -- имя импортируемой процедуры + - library -- имя файла динамической библиотеки (строковая константа) + - function -- имя импортируемой процедуры (строковая константа), если + указана пустая строка, то имя процедуры = proc_name например: - PROCEDURE [win64, "kernel32.dll", "ExitProcess"] exit (code: INTEGER); + PROCEDURE [windows, "kernel32.dll", "ExitProcess"] exit (code: INTEGER); + PROCEDURE [windows, "kernel32.dll", ""] GetTickCount (): INTEGER; В конце объявления может быть добавлено (необязательно) "END proc_name;" @@ -301,7 +333,7 @@ Oberon-реализациях выполнение такой операции соглашения о вызове: VAR - ExitProcess: PROCEDURE [win64] (code: INTEGER); + ExitProcess: PROCEDURE [windows] (code: INTEGER); Для Linux, импортированные процедуры не реализованы. @@ -321,6 +353,8 @@ Oberon-реализациях выполнение такой операции Вызов транслируется так: Proc(SYSTEM.TYPEID(Rec), SYSTEM.ADR(x)) + Скрытые параметры необходимо учитывать при связи с внешними приложениями. + ------------------------------------------------------------------------------ Модуль RTL @@ -343,4 +377,5 @@ Oberon-реализациях выполнение такой операции Разрешается экспортировать только процедуры. Для этого, процедура должна находиться в главном модуле программы, ее имя должно быть отмечено символом -экспорта ("*") и должно быть указано соглашение о вызове. \ No newline at end of file +экспорта ("*") и должно быть указано соглашение о вызове. Нельзя +экспортировать процедуры, которые импортированы из других dll-библиотек. \ No newline at end of file diff --git a/programs/develop/oberon07/tools/RVM32I.ob07 b/programs/develop/oberon07/tools/RVM32I.ob07 new file mode 100644 index 000000000..1aa501c06 --- /dev/null +++ b/programs/develop/oberon07/tools/RVM32I.ob07 @@ -0,0 +1,575 @@ +(* + BSD 2-Clause License + + Copyright (c) 2020, Anton Krotov + All rights reserved. +*) + +(* + RVM32I executor and disassembler + + for win32 only + + Usage: + RVM32I.exe -run [program parameters] + RVM32I.exe -dis +*) + +MODULE RVM32I; + +IMPORT SYSTEM, File, Args, Out, API, HOST, RTL; + + +CONST + + opSTOP = 0; opRET = 1; opENTER = 2; opNEG = 3; opNOT = 4; opABS = 5; + opXCHG = 6; opLDR8 = 7; opLDR16 = 8; opLDR32 = 9; opPUSH = 10; opPUSHC = 11; + opPOP = 12; opJGZ = 13; opJZ = 14; opJNZ = 15; opLLA = 16; opJGA = 17; + opJLA = 18; opJMP = 19; opCALL = 20; opCALLI = 21; + + opMOV = 22; opMUL = 24; opADD = 26; opSUB = 28; opDIV = 30; opMOD = 32; + opSTR8 = 34; opSTR16 = 36; opSTR32 = 38; opINCL = 40; opEXCL = 42; + opIN = 44; opAND = 46; opOR = 48; opXOR = 50; opASR = 52; opLSR = 54; + opLSL = 56; opROR = 58; opMIN = 60; opMAX = 62; opEQ = 64; opNE = 66; + opLT = 68; opLE = 70; opGT = 72; opGE = 74; opBT = 76; + + opMOVC = 23; opMULC = 25; opADDC = 27; opSUBC = 29; opDIVC = 31; opMODC = 33; + opSTR8C = 35; opSTR16C = 37; opSTR32C = 39; opINCLC = 41; opEXCLC = 43; + opINC = 45; opANDC = 47; opORC = 49; opXORC = 51; opASRC = 53; opLSRC = 55; + opLSLC = 57; opRORC = 59; opMINC = 61; opMAXC = 63; opEQC = 65; opNEC = 67; + opLTC = 69; opLEC = 71; opGTC = 73; opGEC = 75; opBTC = 77; + + opLEA = 78; opLABEL = 79; opSYSCALL = 80; + + + ACC = 0; BP = 3; SP = 4; + + Types = 0; + Strings = 1; + Global = 2; + Heap = 3; + Stack = 4; + + +TYPE + + COMMAND = POINTER TO RECORD + + op, param1, param2: INTEGER; + next: COMMAND + + END; + + +VAR + + R: ARRAY 32 OF INTEGER; + + Sections: ARRAY 5 OF RECORD address: INTEGER; name: ARRAY 16 OF CHAR END; + + first, last: COMMAND; + + Labels: ARRAY 30000 OF COMMAND; + + F: INTEGER; buf: ARRAY 65536 OF BYTE; cnt: INTEGER; + + +PROCEDURE syscall (ptr: INTEGER); +VAR + fn, p1, p2, p3, p4, r: INTEGER; + + proc2: PROCEDURE (a, b: INTEGER): INTEGER; + proc3: PROCEDURE (a, b, c: INTEGER): INTEGER; + proc4: PROCEDURE (a, b, c, d: INTEGER): INTEGER; + +BEGIN + SYSTEM.GET(ptr, fn); + SYSTEM.GET(ptr + 4, p1); + SYSTEM.GET(ptr + 8, p2); + SYSTEM.GET(ptr + 12, p3); + SYSTEM.GET(ptr + 16, p4); + CASE fn OF + | 0: HOST.ExitProcess(p1) + | 1: SYSTEM.PUT(SYSTEM.ADR(proc2), SYSTEM.ADR(HOST.GetCurrentDirectory)); + r := proc2(p1, p2) + | 2: SYSTEM.PUT(SYSTEM.ADR(proc3), SYSTEM.ADR(HOST.GetArg)); + r := proc3(p1 + 2, p2, p3) + | 3: SYSTEM.PUT(SYSTEM.ADR(proc4), SYSTEM.ADR(HOST.FileRead)); + SYSTEM.PUT(ptr, proc4(p1, p2, p3, p4)) + | 4: SYSTEM.PUT(SYSTEM.ADR(proc4), SYSTEM.ADR(HOST.FileWrite)); + SYSTEM.PUT(ptr, proc4(p1, p2, p3, p4)) + | 5: SYSTEM.PUT(SYSTEM.ADR(proc2), SYSTEM.ADR(HOST.FileCreate)); + SYSTEM.PUT(ptr, proc2(p1, p2)) + | 6: HOST.FileClose(p1) + | 7: SYSTEM.PUT(SYSTEM.ADR(proc2), SYSTEM.ADR(HOST.FileOpen)); + SYSTEM.PUT(ptr, proc2(p1, p2)) + | 8: HOST.OutChar(CHR(p1)) + | 9: SYSTEM.PUT(ptr, HOST.GetTickCount()) + |10: SYSTEM.PUT(ptr, HOST.UnixTime()) + |11: SYSTEM.PUT(SYSTEM.ADR(proc2), SYSTEM.ADR(HOST.isRelative)); + SYSTEM.PUT(ptr, proc2(p1, p2)) + |12: SYSTEM.PUT(SYSTEM.ADR(proc2), SYSTEM.ADR(HOST.chmod)); + r := proc2(p1, p2) + END +END syscall; + + +PROCEDURE exec; +VAR + cmd: COMMAND; + param1, param2: INTEGER; + temp: INTEGER; + +BEGIN + cmd := first; + WHILE cmd # NIL DO + param1 := cmd.param1; + param2 := cmd.param2; + CASE cmd.op OF + |opSTOP: cmd := last + |opRET: SYSTEM.MOVE(R[SP], SYSTEM.ADR(cmd), 4); INC(R[SP], 4) + |opENTER: DEC(R[SP], 4); SYSTEM.PUT32(R[SP], R[BP]); R[BP] := R[SP]; WHILE param1 > 0 DO DEC(R[SP], 4); SYSTEM.PUT32(R[SP], 0); DEC(param1) END + |opPOP: SYSTEM.GET32(R[SP], R[param1]); INC(R[SP], 4) + |opNEG: R[param1] := -R[param1] + |opNOT: R[param1] := ORD(-BITS(R[param1])) + |opABS: R[param1] := ABS(R[param1]) + |opXCHG: temp := R[param1]; R[param1] := R[param2]; R[param2] := temp + |opLDR8: SYSTEM.GET8(R[param2], R[param1]); R[param1] := R[param1] MOD 256; + |opLDR16: SYSTEM.GET16(R[param2], R[param1]); R[param1] := R[param1] MOD 65536; + |opLDR32: SYSTEM.GET32(R[param2], R[param1]) + |opPUSH: DEC(R[SP], 4); SYSTEM.PUT32(R[SP], R[param1]) + |opPUSHC: DEC(R[SP], 4); SYSTEM.PUT32(R[SP], param1) + |opJGZ: IF R[param1] > 0 THEN cmd := Labels[cmd.param2] END + |opJZ: IF R[param1] = 0 THEN cmd := Labels[cmd.param2] END + |opJNZ: IF R[param1] # 0 THEN cmd := Labels[cmd.param2] END + |opLLA: SYSTEM.MOVE(SYSTEM.ADR(Labels[cmd.param2]), SYSTEM.ADR(R[param1]), 4) + |opJGA: IF R[ACC] > param1 THEN cmd := Labels[cmd.param2] END + |opJLA: IF R[ACC] < param1 THEN cmd := Labels[cmd.param2] END + |opJMP: cmd := Labels[cmd.param1] + |opCALL: DEC(R[SP], 4); SYSTEM.MOVE(SYSTEM.ADR(cmd), R[SP], 4); cmd := Labels[cmd.param1] + |opCALLI: DEC(R[SP], 4); SYSTEM.MOVE(SYSTEM.ADR(cmd), R[SP], 4); SYSTEM.MOVE(SYSTEM.ADR(R[param1]), SYSTEM.ADR(cmd), 4) + |opMOV: R[param1] := R[param2] + |opMOVC: R[param1] := param2 + |opMUL: R[param1] := R[param1] * R[param2] + |opMULC: R[param1] := R[param1] * param2 + |opADD: INC(R[param1], R[param2]) + |opADDC: INC(R[param1], param2) + |opSUB: DEC(R[param1], R[param2]) + |opSUBC: DEC(R[param1], param2) + |opDIV: R[param1] := R[param1] DIV R[param2] + |opDIVC: R[param1] := R[param1] DIV param2 + |opMOD: R[param1] := R[param1] MOD R[param2] + |opMODC: R[param1] := R[param1] MOD param2 + |opSTR8: SYSTEM.PUT8(R[param1], R[param2]) + |opSTR8C: SYSTEM.PUT8(R[param1], param2) + |opSTR16: SYSTEM.PUT16(R[param1], R[param2]) + |opSTR16C: SYSTEM.PUT16(R[param1], param2) + |opSTR32: SYSTEM.PUT32(R[param1], R[param2]) + |opSTR32C: SYSTEM.PUT32(R[param1], param2) + |opINCL: SYSTEM.GET32(R[param1], temp); SYSTEM.PUT32(R[param1], ORD(BITS(temp) + {R[param2]})) + |opINCLC: SYSTEM.GET32(R[param1], temp); SYSTEM.PUT32(R[param1], ORD(BITS(temp) + {param2})) + |opEXCL: SYSTEM.GET32(R[param1], temp); SYSTEM.PUT32(R[param1], ORD(BITS(temp) - {R[param2]})) + |opEXCLC: SYSTEM.GET32(R[param1], temp); SYSTEM.PUT32(R[param1], ORD(BITS(temp) - {param2})) + |opIN: R[param1] := ORD(R[param1] IN BITS(R[param2])) + |opINC: R[param1] := ORD(R[param1] IN BITS(param2)) + |opAND: R[param1] := ORD(BITS(R[param1]) * BITS(R[param2])) + |opANDC: R[param1] := ORD(BITS(R[param1]) * BITS(param2)) + |opOR: R[param1] := ORD(BITS(R[param1]) + BITS(R[param2])) + |opORC: R[param1] := ORD(BITS(R[param1]) + BITS(param2)) + |opXOR: R[param1] := ORD(BITS(R[param1]) / BITS(R[param2])) + |opXORC: R[param1] := ORD(BITS(R[param1]) / BITS(param2)) + |opASR: R[param1] := ASR(R[param1], R[param2]) + |opASRC: R[param1] := ASR(R[param1], param2) + |opLSR: R[param1] := LSR(R[param1], R[param2]) + |opLSRC: R[param1] := LSR(R[param1], param2) + |opLSL: R[param1] := LSL(R[param1], R[param2]) + |opLSLC: R[param1] := LSL(R[param1], param2) + |opROR: R[param1] := ROR(R[param1], R[param2]) + |opRORC: R[param1] := ROR(R[param1], param2) + |opMIN: R[param1] := MIN(R[param1], R[param2]) + |opMINC: R[param1] := MIN(R[param1], param2) + |opMAX: R[param1] := MAX(R[param1], R[param2]) + |opMAXC: R[param1] := MAX(R[param1], param2) + |opEQ: R[param1] := ORD(R[param1] = R[param2]) + |opEQC: R[param1] := ORD(R[param1] = param2) + |opNE: R[param1] := ORD(R[param1] # R[param2]) + |opNEC: R[param1] := ORD(R[param1] # param2) + |opLT: R[param1] := ORD(R[param1] < R[param2]) + |opLTC: R[param1] := ORD(R[param1] < param2) + |opLE: R[param1] := ORD(R[param1] <= R[param2]) + |opLEC: R[param1] := ORD(R[param1] <= param2) + |opGT: R[param1] := ORD(R[param1] > R[param2]) + |opGTC: R[param1] := ORD(R[param1] > param2) + |opGE: R[param1] := ORD(R[param1] >= R[param2]) + |opGEC: R[param1] := ORD(R[param1] >= param2) + |opBT: R[param1] := ORD((R[param1] < R[param2]) & (R[param1] >= 0)) + |opBTC: R[param1] := ORD((R[param1] < param2) & (R[param1] >= 0)) + |opLEA: R[param1 MOD 256] := Sections[param1 DIV 256].address + param2 + |opLABEL: + |opSYSCALL: syscall(R[param1]) + END; + cmd := cmd.next + END +END exec; + + +PROCEDURE disasm (name: ARRAY OF CHAR; t_count, c_count, glob, heap: INTEGER); +VAR + cmd: COMMAND; + param1, param2, i, t, ptr: INTEGER; + b: BYTE; + + + PROCEDURE String (s: ARRAY OF CHAR); + VAR + n: INTEGER; + + BEGIN + n := LENGTH(s); + IF n > LEN(buf) - cnt THEN + ASSERT(File.Write(F, SYSTEM.ADR(buf[0]), cnt) = cnt); + cnt := 0 + END; + SYSTEM.MOVE(SYSTEM.ADR(s[0]), SYSTEM.ADR(buf[0]) + cnt, n); + INC(cnt, n) + END String; + + + PROCEDURE Ln; + BEGIN + String(0DX + 0AX) + END Ln; + + + PROCEDURE hexdgt (n: INTEGER): CHAR; + BEGIN + IF n < 10 THEN + INC(n, ORD("0")) + ELSE + INC(n, ORD("A") - 10) + END + + RETURN CHR(n) + END hexdgt; + + + PROCEDURE Hex (x: INTEGER); + VAR + str: ARRAY 11 OF CHAR; + n: INTEGER; + + BEGIN + n := 10; + str[10] := 0X; + WHILE n > 2 DO + str[n - 1] := hexdgt(x MOD 16); + x := x DIV 16; + DEC(n) + END; + str[1] := "x"; + str[0] := "0"; + String(str) + END Hex; + + + PROCEDURE Byte (x: BYTE); + VAR + str: ARRAY 5 OF CHAR; + + BEGIN + str[4] := 0X; + str[3] := hexdgt(x MOD 16); + str[2] := hexdgt(x DIV 16); + str[1] := "x"; + str[0] := "0"; + String(str) + END Byte; + + + PROCEDURE Reg (n: INTEGER); + VAR + s: ARRAY 2 OF CHAR; + BEGIN + IF n = BP THEN + String("BP") + ELSIF n = SP THEN + String("SP") + ELSE + String("R"); + s[1] := 0X; + IF n >= 10 THEN + s[0] := CHR(n DIV 10 + ORD("0")); + String(s) + END; + s[0] := CHR(n MOD 10 + ORD("0")); + String(s) + END + END Reg; + + + PROCEDURE Reg2 (r1, r2: INTEGER); + BEGIN + Reg(r1); String(", "); Reg(r2) + END Reg2; + + + PROCEDURE RegC (r, c: INTEGER); + BEGIN + Reg(r); String(", "); Hex(c) + END RegC; + + + PROCEDURE RegL (r, label: INTEGER); + BEGIN + Reg(r); String(", L"); Hex(label) + END RegL; + + +BEGIN + Sections[Types].name := "TYPES"; + Sections[Strings].name := "STRINGS"; + Sections[Global].name := "GLOBAL"; + Sections[Heap].name := "HEAP"; + Sections[Stack].name := "STACK"; + + F := File.Create(name); + ASSERT(F > 0); + cnt := 0; + String("CODE:"); Ln; + cmd := first; + WHILE cmd # NIL DO + param1 := cmd.param1; + param2 := cmd.param2; + CASE cmd.op OF + |opSTOP: String("STOP") + |opRET: String("RET") + |opENTER: String("ENTER "); Hex(param1) + |opPOP: String("POP "); Reg(param1) + |opNEG: String("NEG "); Reg(param1) + |opNOT: String("NOT "); Reg(param1) + |opABS: String("ABS "); Reg(param1) + |opXCHG: String("XCHG "); Reg2(param1, param2) + |opLDR8: String("LDR8 "); Reg2(param1, param2) + |opLDR16: String("LDR16 "); Reg2(param1, param2) + |opLDR32: String("LDR32 "); Reg2(param1, param2) + |opPUSH: String("PUSH "); Reg(param1) + |opPUSHC: String("PUSH "); Hex(param1) + |opJGZ: String("JGZ "); RegL(param1, param2) + |opJZ: String("JZ "); RegL(param1, param2) + |opJNZ: String("JNZ "); RegL(param1, param2) + |opLLA: String("LLA "); RegL(param1, param2) + |opJGA: String("JGA "); Hex(param1); String(", L"); Hex(param2) + |opJLA: String("JLA "); Hex(param1); String(", L"); Hex(param2) + |opJMP: String("JMP L"); Hex(param1) + |opCALL: String("CALL L"); Hex(param1) + |opCALLI: String("CALL "); Reg(param1) + |opMOV: String("MOV "); Reg2(param1, param2) + |opMOVC: String("MOV "); RegC(param1, param2) + |opMUL: String("MUL "); Reg2(param1, param2) + |opMULC: String("MUL "); RegC(param1, param2) + |opADD: String("ADD "); Reg2(param1, param2) + |opADDC: String("ADD "); RegC(param1, param2) + |opSUB: String("SUB "); Reg2(param1, param2) + |opSUBC: String("SUB "); RegC(param1, param2) + |opDIV: String("DIV "); Reg2(param1, param2) + |opDIVC: String("DIV "); RegC(param1, param2) + |opMOD: String("MOD "); Reg2(param1, param2) + |opMODC: String("MOD "); RegC(param1, param2) + |opSTR8: String("STR8 "); Reg2(param1, param2) + |opSTR8C: String("STR8 "); RegC(param1, param2) + |opSTR16: String("STR16 "); Reg2(param1, param2) + |opSTR16C: String("STR16 "); RegC(param1, param2) + |opSTR32: String("STR32 "); Reg2(param1, param2) + |opSTR32C: String("STR32 "); RegC(param1, param2) + |opINCL: String("INCL "); Reg2(param1, param2) + |opINCLC: String("INCL "); RegC(param1, param2) + |opEXCL: String("EXCL "); Reg2(param1, param2) + |opEXCLC: String("EXCL "); RegC(param1, param2) + |opIN: String("IN "); Reg2(param1, param2) + |opINC: String("IN "); RegC(param1, param2) + |opAND: String("AND "); Reg2(param1, param2) + |opANDC: String("AND "); RegC(param1, param2) + |opOR: String("OR "); Reg2(param1, param2) + |opORC: String("OR "); RegC(param1, param2) + |opXOR: String("XOR "); Reg2(param1, param2) + |opXORC: String("XOR "); RegC(param1, param2) + |opASR: String("ASR "); Reg2(param1, param2) + |opASRC: String("ASR "); RegC(param1, param2) + |opLSR: String("LSR "); Reg2(param1, param2) + |opLSRC: String("LSR "); RegC(param1, param2) + |opLSL: String("LSL "); Reg2(param1, param2) + |opLSLC: String("LSL "); RegC(param1, param2) + |opROR: String("ROR "); Reg2(param1, param2) + |opRORC: String("ROR "); RegC(param1, param2) + |opMIN: String("MIN "); Reg2(param1, param2) + |opMINC: String("MIN "); RegC(param1, param2) + |opMAX: String("MAX "); Reg2(param1, param2) + |opMAXC: String("MAX "); RegC(param1, param2) + |opEQ: String("EQ "); Reg2(param1, param2) + |opEQC: String("EQ "); RegC(param1, param2) + |opNE: String("NE "); Reg2(param1, param2) + |opNEC: String("NE "); RegC(param1, param2) + |opLT: String("LT "); Reg2(param1, param2) + |opLTC: String("LT "); RegC(param1, param2) + |opLE: String("LE "); Reg2(param1, param2) + |opLEC: String("LE "); RegC(param1, param2) + |opGT: String("GT "); Reg2(param1, param2) + |opGTC: String("GT "); RegC(param1, param2) + |opGE: String("GE "); Reg2(param1, param2) + |opGEC: String("GE "); RegC(param1, param2) + |opBT: String("BT "); Reg2(param1, param2) + |opBTC: String("BT "); RegC(param1, param2) + |opLEA: String("LEA "); Reg(param1 MOD 256); String(", "); String(Sections[param1 DIV 256].name); String(" + "); Hex(param2) + |opLABEL: String("L"); Hex(param1); String(":") + |opSYSCALL: String("SYSCALL "); Reg(param1) + END; + Ln; + cmd := cmd.next + END; + + String("TYPES:"); + ptr := Sections[Types].address; + FOR i := 0 TO t_count - 1 DO + IF i MOD 4 = 0 THEN + Ln; String("WORD ") + ELSE + String(", ") + END; + SYSTEM.GET32(ptr, t); INC(ptr, 4); + Hex(t) + END; + Ln; + + String("STRINGS:"); + ptr := Sections[Strings].address; + FOR i := 0 TO c_count - 1 DO + IF i MOD 8 = 0 THEN + Ln; String("BYTE ") + ELSE + String(", ") + END; + SYSTEM.GET8(ptr, b); INC(ptr); + Byte(b) + END; + Ln; + + String("GLOBAL:"); Ln; + String("WORDS "); Hex(glob); Ln; + String("HEAP:"); Ln; + String("WORDS "); Hex(heap); Ln; + String("STACK:"); Ln; + String("WORDS 8"); Ln; + + ASSERT(File.Write(F, SYSTEM.ADR(buf[0]), cnt) = cnt); + File.Close(F) +END disasm; + + +PROCEDURE GetCommand (adr: INTEGER): COMMAND; +VAR + op, param1, param2: INTEGER; + res: COMMAND; + +BEGIN + op := 0; param1 := 0; param2 := 0; + SYSTEM.GET32(adr, op); + SYSTEM.GET32(adr + 4, param1); + SYSTEM.GET32(adr + 8, param2); + NEW(res); + res.op := op; + res.param1 := param1; + res.param2 := param2; + res.next := NIL + + RETURN res +END GetCommand; + + +PROCEDURE main; +VAR + name, param: ARRAY 1024 OF CHAR; + cmd: COMMAND; + file, fsize, n: INTEGER; + + descr: ARRAY 12 OF INTEGER; + + offTypes, offStrings, GlobalSize, HeapStackSize, DescrSize: INTEGER; + +BEGIN + Out.Open; + Args.GetArg(1, name); + F := File.Open(name, File.OPEN_R); + IF F > 0 THEN + DescrSize := LEN(descr) * SYSTEM.SIZE(INTEGER); + fsize := File.Seek(F, 0, File.SEEK_END); + ASSERT(fsize > DescrSize); + file := API._NEW(fsize); + ASSERT(file # 0); + n := File.Seek(F, 0, File.SEEK_BEG); + ASSERT(fsize = File.Read(F, file, fsize)); + File.Close(F); + + SYSTEM.MOVE(file + fsize - DescrSize, SYSTEM.ADR(descr[0]), DescrSize); + offTypes := descr[0]; + ASSERT(offTypes < fsize - DescrSize); + ASSERT(offTypes > 0); + ASSERT(offTypes MOD 12 = 0); + offStrings := descr[1]; + ASSERT(offStrings < fsize - DescrSize); + ASSERT(offStrings > 0); + ASSERT(offStrings MOD 4 = 0); + ASSERT(offStrings > offTypes); + GlobalSize := descr[2]; + ASSERT(GlobalSize > 0); + HeapStackSize := descr[3]; + ASSERT(HeapStackSize > 0); + + Sections[Types].address := API._NEW(offStrings - offTypes); + ASSERT(Sections[Types].address # 0); + SYSTEM.MOVE(file + offTypes, Sections[Types].address, offStrings - offTypes); + + Sections[Strings].address := API._NEW(fsize - offStrings - DescrSize); + ASSERT(Sections[Strings].address # 0); + SYSTEM.MOVE(file + offStrings, Sections[Strings].address, fsize - offStrings - DescrSize); + + Sections[Global].address := API._NEW(GlobalSize * 4); + ASSERT(Sections[Global].address # 0); + + Sections[Heap].address := API._NEW(HeapStackSize * 4); + ASSERT(Sections[Heap].address # 0); + + Sections[Stack].address := Sections[Heap].address + HeapStackSize * 4 - 32; + + n := offTypes DIV 12; + first := GetCommand(file + offTypes - n * 12); + last := first; + DEC(n); + WHILE n > 0 DO + cmd := GetCommand(file + offTypes - n * 12); + IF cmd.op = opLABEL THEN + Labels[cmd.param1] := cmd + END; + last.next := cmd; + last := cmd; + DEC(n) + END; + file := API._DISPOSE(file); + Args.GetArg(2, param); + IF param = "-dis" THEN + Args.GetArg(3, name); + IF name # "" THEN + disasm(name, (offStrings - offTypes) DIV 4, fsize - offStrings - DescrSize, GlobalSize, HeapStackSize) + END + ELSIF param = "-run" THEN + exec + END + ELSE + Out.String("file not found"); Out.Ln + END +END main; + + +BEGIN + ASSERT(RTL.bit_depth = 32); + main +END RVM32I. \ No newline at end of file

D_g(IG4t9?^|qA}WETUvUd8 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%0Ay9wAQ_)Iwq&W03hj5EW_kCkT#4wb6o`q%XP} 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