Browse Source

Merge branch source:main into main

Massimo Magnano 2 years ago
parent
commit
9f27748182

+ 1 - 1
packages/fcl-js/src/jssrcmap.pas

@@ -704,7 +704,7 @@ var
       buf.Write(s[1],length(s)*sizeof(char));
       buf.Write(s[1],length(s)*sizeof(char));
   end;
   end;
 
 
-  procedure AddChar(c: char);
+  procedure AddChar({%H-}c: char);
   begin
   begin
     buf.Write(c,sizeof(char));
     buf.Write(c,sizeof(char));
   end;
   end;

+ 16 - 16
packages/fcl-js/src/jswriter.pp

@@ -1,4 +1,4 @@
-{ ********************************************************************* 
+{ *********************************************************************
     This file is part of the Free Component Library (FCL)
     This file is part of the Free Component Library (FCL)
     Copyright (c) 2016 Michael Van Canneyt.
     Copyright (c) 2016 Michael Van Canneyt.
        
        
@@ -29,10 +29,8 @@ uses
 Type
 Type
   {$ifdef pas2js}
   {$ifdef pas2js}
   TJSWriterString = UnicodeString;
   TJSWriterString = UnicodeString;
-  TJSWriterChar = WideChar;
   {$else}
   {$else}
   TJSWriterString = AnsiString;
   TJSWriterString = AnsiString;
-  TJSWriterChar = AnsiChar;
   {$endif}
   {$endif}
 
 
   TTextWriter = class;
   TTextWriter = class;
@@ -97,7 +95,7 @@ Type
   end;
   end;
   {$endif}
   {$endif}
 
 
-  TBufferWriter_Buffer = Array of {$ifdef fpc}byte{$else}string{$endif};
+  TBufferWriter_Buffer = Array of {$IFDEF PAS2JS}String{$ELSE}Byte{$ENDIF};
 
 
   { TBufferWriter }
   { TBufferWriter }
 
 
@@ -382,22 +380,24 @@ begin
   FCapacity:=FBufPos;
   FCapacity:=FBufPos;
 end;
 end;
 {$else}
 {$else}
-Var
-  DesLen,MinLen : Integer;
+var
+  DesLen,MinLen : Cardinal;
 
 
 begin
 begin
-  Result:=Length(S)*SizeOf(TJSWriterChar);
-  if Result=0 then exit;
-  MinLen:=Result+integer(FBufPos);
-  If (MinLen>integer(Capacity)) then
+  Result := Length(S);
+  if Result = 0 then
+    Exit;
+
+  MinLen:=Result + FBufPos;
+  if MinLen > Capacity then
     begin
     begin
-    DesLen:=(FCapacity*3) div 2;
-    if DesLen>MinLen then
-      MinLen:=DesLen;
-    Capacity:=MinLen;
+    DesLen:=(FCapacity * 3) div 2;
+    if DesLen > MinLen then
+      MinLen := DesLen;
+    Capacity := MinLen;
     end;
     end;
-  Move(S[1],FBuffer[FBufPos],Result);
-  FBufPos:=integer(FBufPos)+Result;
+  Move(S[1], FBuffer[FBufPos], Result);
+  FBufPos:=FBufPos + Result;
 end;
 end;
 {$endif}
 {$endif}
 
 

+ 2 - 1
packages/fcl-passrc/src/pasresolver.pp

@@ -29909,7 +29909,8 @@ begin
       btIntSingle,
       btIntSingle,
       btUIntSingle,
       btUIntSingle,
       btIntDouble,
       btIntDouble,
-      btUIntDouble:
+      btUIntDouble,
+      btCurrency:
         begin
         begin
         Result:=TResEvalRangeInt.Create;
         Result:=TResEvalRangeInt.Create;
         TResEvalRangeInt(Result).ElKind:=revskInt;
         TResEvalRangeInt(Result).ElKind:=revskInt;

+ 1 - 1
packages/pastojs/src/pas2jslogger.pp

@@ -21,7 +21,7 @@
 unit Pas2jsLogger;
 unit Pas2jsLogger;
 
 
 {$mode objfpc}{$H+}
 {$mode objfpc}{$H+}
-
+{$WARN 6018 off : Unreachable code}
 {$i pas2js_defines.inc}
 {$i pas2js_defines.inc}
 
 
 interface
 interface

+ 47 - 0
packages/pastojs/tests/tcmodules.pas

@@ -940,6 +940,7 @@ type
     procedure TestRangeChecks_StringIndex;
     procedure TestRangeChecks_StringIndex;
     procedure TestRangeChecks_TypecastInt;
     procedure TestRangeChecks_TypecastInt;
     procedure TestRangeChecks_TypeHelperInt;
     procedure TestRangeChecks_TypeHelperInt;
+    procedure TestRangeChecks_AssignCurrency;
 
 
     // Async/AWait
     // Async/AWait
     Procedure TestAsync_Proc;
     Procedure TestAsync_Proc;
@@ -34809,6 +34810,52 @@ begin
     '']));
     '']));
 end;
 end;
 
 
+procedure TTestModule.TestRangeChecks_AssignCurrency;
+begin
+  Scanner.Options:=Scanner.Options+[po_CAssignments];
+  StartProgram(false);
+  Add([
+  '{$R+}',
+  'var',
+  '  c: currency = 2.34;',
+  '  i: double;',
+  'procedure DoIt(p: currency);',
+  'begin',
+  '  c:=i;',
+  '  c+=i;',
+  '  c:=1;',
+  'end;',
+  '{$R-}',
+  'procedure DoSome;',
+  'begin',
+  '  DoIt(i);',
+  '  c:=i;',
+  '  c:=2;',
+  'end;',
+  'begin',
+  '{$R+}',
+  '']);
+  ConvertProgram;
+  CheckSource('TestRangeChecks_AssignCurrency',
+    LinesToStr([ // statements
+    'this.c = 2.34;',
+    'this.i = 0.0;',
+    'this.DoIt = function (p) {',
+    '  rtl.rc(p, -922337203685477, 922337203685477);',
+    '  $mod.c = rtl.rc(rtl.trunc($mod.i * 10000), -922337203685477, 922337203685477);',
+    '  rtl.rc($mod.c += rtl.trunc($mod.i * 10000), -922337203685477, 922337203685477);',
+    '  $mod.c = 10000;',
+    '};',
+    'this.DoSome = function () {',
+    '  $mod.DoIt($mod.i * 10000);',
+    '  $mod.c = rtl.trunc($mod.i * 10000);',
+    '  $mod.c = 20000;',
+    '};',
+    '']),
+    LinesToStr([ // $mod.$main
+    '']));
+end;
+
 procedure TTestModule.TestAsync_Proc;
 procedure TTestModule.TestAsync_Proc;
 begin
 begin
   StartProgram(false);
   StartProgram(false);

+ 1 - 1
packages/paszlib/fpmake.pp

@@ -20,7 +20,7 @@ begin
     P.Directory:=ADirectory;
     P.Directory:=ADirectory;
 {$endif ALLPACKAGES}
 {$endif ALLPACKAGES}
     P.Version:='3.3.1';
     P.Version:='3.3.1';
-    P.OSes := P.OSes - [embedded,msdos,win16,macosclassic,palmos,zxspectrum,msxdos,amstradcpc,sinclairql,wasi];
+    P.OSes := P.OSes - [embedded,msdos,win16,macosclassic,palmos,zxspectrum,msxdos,amstradcpc,sinclairql];
     if Defaults.CPU=jvm then
     if Defaults.CPU=jvm then
       P.OSes := P.OSes - [java,android];
       P.OSes := P.OSes - [java,android];
 
 

+ 373 - 335
packages/paszlib/src/infblock.pas

@@ -1,7 +1,5 @@
 unit infblock;
 unit infblock;
 
 
-{$goto on}
-
 { infblock.h and
 { infblock.h and
   infblock.c -- interpret and process block types to last block
   infblock.c -- interpret and process block types to last block
   Copyright (C) 1995-1998 Mark Adler
   Copyright (C) 1995-1998 Mark Adler
@@ -172,10 +170,6 @@ end;
 function inflate_blocks (var s : inflate_blocks_state;
 function inflate_blocks (var s : inflate_blocks_state;
                          var z : z_stream;
                          var z : z_stream;
                          r : integer) : integer;           { initial return code }
                          r : integer) : integer;           { initial return code }
-label
-  start_btree, start_dtree,
-  start_blkdone, start_dry,
-  start_codes;
 
 
 var
 var
   t : cardinal;               { temporary storage }
   t : cardinal;               { temporary storage }
@@ -194,6 +188,350 @@ var
   i, j, c : cardinal;
   i, j, c : cardinal;
 var
 var
   cs : pInflate_codes_state;
   cs : pInflate_codes_state;
+  
+  procedure do_btree;
+  
+  begin
+    while (s.sub.trees.index < 4 + (s.sub.trees.table shr 10)) do
+    begin
+      {NEEDBITS(3);}
+      while (k < 3) do
+      begin
+        {NEEDBYTE;}
+        if (n <> 0) then
+          r :=Z_OK
+        else
+        begin
+          {UPDATE}
+          s.bitb := b;
+          s.bitk := k;
+          z.avail_in := n;
+          Inc(z.total_in, ptruint(p)-ptruint(z.next_in));
+          z.next_in := p;
+          s.write := q;
+          inflate_blocks := inflate_flush(s,z,r);
+          exit;
+        end;
+        dec(n);
+        b := b or (cardinal(p^) shl k);
+        Inc(p);
+        Inc(k, 8);
+      end;
+
+      s.sub.trees.blens^[border[s.sub.trees.index]] := cardinal(b) and 7;
+      Inc(s.sub.trees.index);
+      {DUMPBITS(3);}
+      b := b shr 3;
+      dec(k, 3);
+    end;
+    while (s.sub.trees.index < 19) do
+    begin
+      s.sub.trees.blens^[border[s.sub.trees.index]] := 0;
+      Inc(s.sub.trees.index);
+    end;
+    s.sub.trees.bb := 7;
+    t := inflate_trees_bits(s.sub.trees.blens^, s.sub.trees.bb,
+                            s.sub.trees.tb, s.hufts^, z);
+    if (t <> Z_OK) then
+    begin
+      freemem(s.sub.trees.blens);
+      s.sub.trees.blens := nil;
+      r := t;
+      if (r = Z_DATA_ERROR) then
+        s.mode := BLKBAD;
+      { update pointers and return }
+      s.bitb := b;
+      s.bitk := k;
+      z.avail_in := n;
+      Inc(z.total_in, ptruint(p) - ptruint(z.next_in));
+      z.next_in := p;
+      s.write := q;
+      inflate_blocks := inflate_flush(s,z,r);
+      exit;
+    end;
+    s.sub.trees.index := 0;
+    {$IFDEF ZLIB_DEBUG}
+    Tracev('inflate:       bits tree ok');
+    {$ENDIF}
+    s.mode := DTREE;
+    { fall through again }
+  end;
+  
+  procedure do_dtree;
+  
+  begin
+    while TRUE do
+    begin
+      t := s.sub.trees.table;
+      if not (s.sub.trees.index < 258 +
+                                 (t and $1f) + ((t shr 5) and $1f)) then
+        break;
+      t := s.sub.trees.bb;
+      {NEEDBITS(t);}
+      while (k < t) do
+      begin
+        {NEEDBYTE;}
+        if (n <> 0) then
+          r :=Z_OK
+        else
+        begin
+          {UPDATE}
+          s.bitb := b;
+          s.bitk := k;
+          z.avail_in := n;
+          Inc(z.total_in, ptruint(p)-ptruint(z.next_in));
+          z.next_in := p;
+          s.write := q;
+          inflate_blocks := inflate_flush(s,z,r);
+          exit;
+        end;
+        dec(n);
+        b := b or (cardinal(p^) shl k);
+        Inc(p);
+        Inc(k, 8);
+      end;
+
+      h := s.sub.trees.tb;
+      Inc(h, cardinal(b) and inflate_mask[t]);
+      t := h^.Bits;
+      c := h^.Base;
+
+      if (c < 16) then
+      begin
+        {DUMPBITS(t);}
+        b := b shr t;
+        dec(k, t);
+
+        s.sub.trees.blens^[s.sub.trees.index] := c;
+        Inc(s.sub.trees.index);
+      end
+      else { c = 16..18 }
+      begin
+        if c = 18 then
+        begin
+          i := 7;
+          j := 11;
+        end
+        else
+        begin
+          i := c - 14;
+          j := 3;
+        end;
+        {NEEDBITS(t + i);}
+        while (k < t + i) do
+        begin
+          {NEEDBYTE;}
+          if (n <> 0) then
+            r :=Z_OK
+          else
+          begin
+            {UPDATE}
+            s.bitb := b;
+            s.bitk := k;
+            z.avail_in := n;
+            Inc(z.total_in, ptruint(p)-ptruint(z.next_in));
+            z.next_in := p;
+            s.write := q;
+            inflate_blocks := inflate_flush(s,z,r);
+            exit;
+          end;
+          dec(n);
+          b := b or (cardinal(p^) shl k);
+          Inc(p);
+          Inc(k, 8);
+        end;
+
+        {DUMPBITS(t);}
+        b := b shr t;
+        dec(k, t);
+
+        Inc(j, cardinal(b) and inflate_mask[i]);
+        {DUMPBITS(i);}
+        b := b shr i;
+        dec(k, i);
+
+        i := s.sub.trees.index;
+        t := s.sub.trees.table;
+        if (i + j > 258 + (t and $1f) + ((t shr 5) and $1f)) or
+           ((c = 16) and (i < 1)) then
+        begin
+          freemem(s.sub.trees.blens);
+          s.sub.trees.blens := nil;
+          s.mode := BLKBAD;
+          z.msg := 'invalid bit length repeat';
+          r := Z_DATA_ERROR;
+          { update pointers and return }
+          s.bitb := b;
+          s.bitk := k;
+          z.avail_in := n;
+          Inc(z.total_in, ptruint(p) - ptruint(z.next_in));
+          z.next_in := p;
+          s.write := q;
+          inflate_blocks := inflate_flush(s,z,r);
+          exit;
+        end;
+        if c = 16 then
+          c := s.sub.trees.blens^[i - 1]
+        else
+          c := 0;
+        repeat
+          s.sub.trees.blens^[i] := c;
+          Inc(i);
+          dec(j);
+        until (j=0);
+        s.sub.trees.index := i;
+      end;
+    end; { while }
+    s.sub.trees.tb := nil;
+    begin
+      bl := 9;         { must be <= 9 for lookahead assumptions }
+      bd := 6;         { must be <= 9 for lookahead assumptions }
+      t := s.sub.trees.table;
+      t := inflate_trees_dynamic(257 + (t and $1f),
+              1 + ((t shr 5) and $1f),
+              s.sub.trees.blens^, bl, bd, tl, td, s.hufts^, z);
+      freemem(s.sub.trees.blens);
+      s.sub.trees.blens := nil;
+      if (t <> Z_OK) then
+      begin
+        if (t = cardinal(Z_DATA_ERROR)) then
+          s.mode := BLKBAD;
+        r := t;
+        { update pointers and return }
+        s.bitb := b;
+        s.bitk := k;
+        z.avail_in := n;
+        Inc(z.total_in, ptruint(p) - ptruint(z.next_in));
+        z.next_in := p;
+        s.write := q;
+        inflate_blocks := inflate_flush(s,z,r);
+        exit;
+      end;
+      {$IFDEF ZLIB_DEBUG}
+      Tracev('inflate:       trees ok');
+      {$ENDIF}          
+      { c renamed to cs }
+      cs := inflate_codes_new(bl, bd, tl, td, z);
+      if (cs = nil) then
+      begin
+        r := Z_MEM_ERROR;
+        { update pointers and return }
+        s.bitb := b;
+        s.bitk := k;
+        z.avail_in := n;
+        Inc(z.total_in, ptruint(p) - ptruint(z.next_in));
+        z.next_in := p;
+        s.write := q;
+        inflate_blocks := inflate_flush(s,z,r);
+        exit;
+      end;
+      s.sub.decode.codes := cs;
+    end;
+    s.mode := CODES;
+  end;
+  
+  function do_codes: boolean;
+  
+  begin
+    { update pointers }
+    s.bitb := b;
+    s.bitk := k;
+    z.avail_in := n;
+    Inc(z.total_in, ptruint(p) - ptruint(z.next_in));
+    z.next_in := p;
+    s.write := q;
+
+    r := inflate_codes(s, z, r);
+    if (r <> Z_STREAM_END) then
+    begin
+      inflate_blocks := inflate_flush(s, z, r);
+      exit;
+    end;
+    r := Z_OK;
+    inflate_codes_free(s.sub.decode.codes, z);
+    { load local pointers }
+    p := z.next_in;
+    n := z.avail_in;
+    b := s.bitb;
+    k := s.bitk;
+    q := s.write;
+    if ptruint(q) < ptruint(s.read) then
+      m := cardinal(ptruint(s.read)-ptruint(q)-1)
+    else
+      m := cardinal(ptruint(s.zend)-ptruint(q));
+    {$IFDEF ZLIB_DEBUG}
+    if (ptruint(q) >= ptruint(s.read)) then
+      Tracev('inflate:       codes end '+
+          IntToStr(z.total_out + ptruint(q) - ptruint(s.read)) + ' total out')
+    else
+      Tracev('inflate:       codes end '+
+              IntToStr(z.total_out + ptruint(s.zend) - ptruint(s.read) +
+              ptruint(q) - ptruint(s.window)) +  ' total out');
+    {$ENDIF}
+    if (not s.last) then
+    begin
+      s.mode := ZTYPE;
+      exit(false); { break for switch statement in C-code }
+    end;
+    {$ifndef patch112}
+    if (k > 7) then           { return unused byte, if any }
+    begin
+      {$IFDEF ZLIB_DEBUG}
+      Assert(k < 16, 'inflate_codes grabbed too many bytes');
+      {$ENDIF}
+      dec(k, 8);
+      inc(n);
+      dec(p);                    { can always return one }
+    end;
+    {$endif}
+    s.mode := DRY;
+    do_codes:=true;
+  end;
+
+  procedure do_dry;
+  
+  begin
+    {FLUSH}
+    s.write := q;
+    r := inflate_flush(s,z,r);
+    q := s.write;
+
+    { not needed anymore, we are done:
+    if ptruint(q) < ptruint(s.read) then
+      m := cardinal(ptruint(s.read)-ptruint(q)-1)
+    else
+      m := cardinal(ptruint(s.zend)-ptruint(q));
+    }
+
+    if (s.read <> s.write) then
+    begin
+      { update pointers and return }
+      s.bitb := b;
+      s.bitk := k;
+      z.avail_in := n;
+      Inc(z.total_in, ptruint(p) - ptruint(z.next_in));
+      z.next_in := p;
+      s.write := q;
+      inflate_blocks := inflate_flush(s,z,r);
+      exit;
+    end;
+    s.mode := BLKDONE;
+  end;
+
+  procedure do_blkdone;
+    
+  begin
+    r := Z_STREAM_END;
+    { update pointers and return }
+    s.bitb := b;
+    s.bitk := k;
+    z.avail_in := n;
+    Inc(z.total_in, ptruint(p) - ptruint(z.next_in));
+    z.next_in := p;
+    s.write := q;
+    inflate_blocks := inflate_flush(s,z,r);
+  end;
+  
 begin
 begin
   { copy input/output information to locals }
   { copy input/output information to locals }
   p := z.next_in;
   p := z.next_in;
@@ -542,350 +880,50 @@ begin
         s.mode := BTREE;
         s.mode := BTREE;
         { fall trough case is handled by the while }
         { fall trough case is handled by the while }
         { try GOTO for speed - Nomssi }
         { try GOTO for speed - Nomssi }
-        goto start_btree;
+        do_btree;
+        do_dtree;
+        if not do_codes then 
+          continue;
+        do_dry;
+        do_blkdone;
+        exit;
       end;
       end;
     BTREE:
     BTREE:
       begin
       begin
-        start_btree:
-        while (s.sub.trees.index < 4 + (s.sub.trees.table shr 10)) do
-        begin
-          {NEEDBITS(3);}
-          while (k < 3) do
-          begin
-            {NEEDBYTE;}
-            if (n <> 0) then
-              r :=Z_OK
-            else
-            begin
-              {UPDATE}
-              s.bitb := b;
-              s.bitk := k;
-              z.avail_in := n;
-              Inc(z.total_in, ptruint(p)-ptruint(z.next_in));
-              z.next_in := p;
-              s.write := q;
-              inflate_blocks := inflate_flush(s,z,r);
-              exit;
-            end;
-            dec(n);
-            b := b or (cardinal(p^) shl k);
-            Inc(p);
-            Inc(k, 8);
-          end;
-
-          s.sub.trees.blens^[border[s.sub.trees.index]] := cardinal(b) and 7;
-          Inc(s.sub.trees.index);
-          {DUMPBITS(3);}
-          b := b shr 3;
-          dec(k, 3);
-        end;
-        while (s.sub.trees.index < 19) do
-        begin
-          s.sub.trees.blens^[border[s.sub.trees.index]] := 0;
-          Inc(s.sub.trees.index);
-        end;
-        s.sub.trees.bb := 7;
-        t := inflate_trees_bits(s.sub.trees.blens^, s.sub.trees.bb,
-                                s.sub.trees.tb, s.hufts^, z);
-        if (t <> Z_OK) then
-        begin
-          freemem(s.sub.trees.blens);
-          s.sub.trees.blens := nil;
-          r := t;
-          if (r = Z_DATA_ERROR) then
-            s.mode := BLKBAD;
-          { update pointers and return }
-          s.bitb := b;
-          s.bitk := k;
-          z.avail_in := n;
-          Inc(z.total_in, ptruint(p) - ptruint(z.next_in));
-          z.next_in := p;
-          s.write := q;
-          inflate_blocks := inflate_flush(s,z,r);
-          exit;
-        end;
-        s.sub.trees.index := 0;
-        {$IFDEF ZLIB_DEBUG}
-        Tracev('inflate:       bits tree ok');
-        {$ENDIF}
-        s.mode := DTREE;
-        { fall through again }
-        goto start_dtree;
+        do_btree;
+        do_dtree;
+        if not do_codes then
+          continue;
+        do_dry;
+        do_blkdone;
+        exit;
       end;
       end;
     DTREE:
     DTREE:
       begin
       begin
-        start_dtree:
-        while TRUE do
-        begin
-          t := s.sub.trees.table;
-          if not (s.sub.trees.index < 258 +
-                                     (t and $1f) + ((t shr 5) and $1f)) then
-            break;
-          t := s.sub.trees.bb;
-          {NEEDBITS(t);}
-          while (k < t) do
-          begin
-            {NEEDBYTE;}
-            if (n <> 0) then
-              r :=Z_OK
-            else
-            begin
-              {UPDATE}
-              s.bitb := b;
-              s.bitk := k;
-              z.avail_in := n;
-              Inc(z.total_in, ptruint(p)-ptruint(z.next_in));
-              z.next_in := p;
-              s.write := q;
-              inflate_blocks := inflate_flush(s,z,r);
-              exit;
-            end;
-            dec(n);
-            b := b or (cardinal(p^) shl k);
-            Inc(p);
-            Inc(k, 8);
-          end;
-
-          h := s.sub.trees.tb;
-          Inc(h, cardinal(b) and inflate_mask[t]);
-          t := h^.Bits;
-          c := h^.Base;
-
-          if (c < 16) then
-          begin
-            {DUMPBITS(t);}
-            b := b shr t;
-            dec(k, t);
-
-            s.sub.trees.blens^[s.sub.trees.index] := c;
-            Inc(s.sub.trees.index);
-          end
-          else { c = 16..18 }
-          begin
-            if c = 18 then
-            begin
-              i := 7;
-              j := 11;
-            end
-            else
-            begin
-              i := c - 14;
-              j := 3;
-            end;
-            {NEEDBITS(t + i);}
-            while (k < t + i) do
-            begin
-              {NEEDBYTE;}
-              if (n <> 0) then
-                r :=Z_OK
-              else
-              begin
-                {UPDATE}
-                s.bitb := b;
-                s.bitk := k;
-                z.avail_in := n;
-                Inc(z.total_in, ptruint(p)-ptruint(z.next_in));
-                z.next_in := p;
-                s.write := q;
-                inflate_blocks := inflate_flush(s,z,r);
-                exit;
-              end;
-              dec(n);
-              b := b or (cardinal(p^) shl k);
-              Inc(p);
-              Inc(k, 8);
-            end;
-
-            {DUMPBITS(t);}
-            b := b shr t;
-            dec(k, t);
-
-            Inc(j, cardinal(b) and inflate_mask[i]);
-            {DUMPBITS(i);}
-            b := b shr i;
-            dec(k, i);
-
-            i := s.sub.trees.index;
-            t := s.sub.trees.table;
-            if (i + j > 258 + (t and $1f) + ((t shr 5) and $1f)) or
-               ((c = 16) and (i < 1)) then
-            begin
-              freemem(s.sub.trees.blens);
-              s.sub.trees.blens := nil;
-              s.mode := BLKBAD;
-              z.msg := 'invalid bit length repeat';
-              r := Z_DATA_ERROR;
-              { update pointers and return }
-              s.bitb := b;
-              s.bitk := k;
-              z.avail_in := n;
-              Inc(z.total_in, ptruint(p) - ptruint(z.next_in));
-              z.next_in := p;
-              s.write := q;
-              inflate_blocks := inflate_flush(s,z,r);
-              exit;
-            end;
-            if c = 16 then
-              c := s.sub.trees.blens^[i - 1]
-            else
-              c := 0;
-            repeat
-              s.sub.trees.blens^[i] := c;
-              Inc(i);
-              dec(j);
-            until (j=0);
-            s.sub.trees.index := i;
-          end;
-        end; { while }
-        s.sub.trees.tb := nil;
-        begin
-          bl := 9;         { must be <= 9 for lookahead assumptions }
-          bd := 6;         { must be <= 9 for lookahead assumptions }
-          t := s.sub.trees.table;
-          t := inflate_trees_dynamic(257 + (t and $1f),
-                  1 + ((t shr 5) and $1f),
-                  s.sub.trees.blens^, bl, bd, tl, td, s.hufts^, z);
-          freemem(s.sub.trees.blens);
-          s.sub.trees.blens := nil;
-          if (t <> Z_OK) then
-          begin
-            if (t = cardinal(Z_DATA_ERROR)) then
-              s.mode := BLKBAD;
-            r := t;
-            { update pointers and return }
-            s.bitb := b;
-            s.bitk := k;
-            z.avail_in := n;
-            Inc(z.total_in, ptruint(p) - ptruint(z.next_in));
-            z.next_in := p;
-            s.write := q;
-            inflate_blocks := inflate_flush(s,z,r);
-            exit;
-          end;
-          {$IFDEF ZLIB_DEBUG}
-          Tracev('inflate:       trees ok');
-          {$ENDIF}          
-          { c renamed to cs }
-          cs := inflate_codes_new(bl, bd, tl, td, z);
-          if (cs = nil) then
-          begin
-            r := Z_MEM_ERROR;
-            { update pointers and return }
-            s.bitb := b;
-            s.bitk := k;
-            z.avail_in := n;
-            Inc(z.total_in, ptruint(p) - ptruint(z.next_in));
-            z.next_in := p;
-            s.write := q;
-            inflate_blocks := inflate_flush(s,z,r);
-            exit;
-          end;
-          s.sub.decode.codes := cs;
-        end;
-        s.mode := CODES;
-        { yet another falltrough }
-        goto start_codes;
+        do_dtree;
+        if not do_codes then 
+          continue;
+        do_dry;
+        do_blkdone;
+        exit;
       end;
       end;
     CODES:
     CODES:
       begin
       begin
-        start_codes:
-        { update pointers }
-        s.bitb := b;
-        s.bitk := k;
-        z.avail_in := n;
-        Inc(z.total_in, ptruint(p) - ptruint(z.next_in));
-        z.next_in := p;
-        s.write := q;
-
-        r := inflate_codes(s, z, r);
-        if (r <> Z_STREAM_END) then
-        begin
-          inflate_blocks := inflate_flush(s, z, r);
-          exit;
-        end;
-        r := Z_OK;
-        inflate_codes_free(s.sub.decode.codes, z);
-        { load local pointers }
-        p := z.next_in;
-        n := z.avail_in;
-        b := s.bitb;
-        k := s.bitk;
-        q := s.write;
-        if ptruint(q) < ptruint(s.read) then
-          m := cardinal(ptruint(s.read)-ptruint(q)-1)
-        else
-          m := cardinal(ptruint(s.zend)-ptruint(q));
-        {$IFDEF ZLIB_DEBUG}
-        if (ptruint(q) >= ptruint(s.read)) then
-          Tracev('inflate:       codes end '+
-              IntToStr(z.total_out + ptruint(q) - ptruint(s.read)) + ' total out')
-        else
-          Tracev('inflate:       codes end '+
-                  IntToStr(z.total_out + ptruint(s.zend) - ptruint(s.read) +
-                  ptruint(q) - ptruint(s.window)) +  ' total out');
-        {$ENDIF}
-        if (not s.last) then
-        begin
-          s.mode := ZTYPE;
-          continue; { break for switch statement in C-code }
-        end;
-        {$ifndef patch112}
-        if (k > 7) then           { return unused byte, if any }
-        begin
-          {$IFDEF ZLIB_DEBUG}
-          Assert(k < 16, 'inflate_codes grabbed too many bytes');
-          {$ENDIF}
-          dec(k, 8);
-          inc(n);
-          dec(p);                    { can always return one }
-        end;
-        {$endif}
-        s.mode := DRY;
-        { another falltrough }
-        goto start_dry;
+        if not do_codes then 
+          continue;
+        do_dry;
+        do_blkdone;
+        exit;
       end;
       end;
     DRY:
     DRY:
       begin
       begin
-        start_dry:
-        {FLUSH}
-        s.write := q;
-        r := inflate_flush(s,z,r);
-        q := s.write;
-
-        { not needed anymore, we are done:
-        if ptruint(q) < ptruint(s.read) then
-          m := cardinal(ptruint(s.read)-ptruint(q)-1)
-        else
-          m := cardinal(ptruint(s.zend)-ptruint(q));
-        }
-
-        if (s.read <> s.write) then
-        begin
-          { update pointers and return }
-          s.bitb := b;
-          s.bitk := k;
-          z.avail_in := n;
-          Inc(z.total_in, ptruint(p) - ptruint(z.next_in));
-          z.next_in := p;
-          s.write := q;
-          inflate_blocks := inflate_flush(s,z,r);
-          exit;
-        end;
-        s.mode := BLKDONE;
-        goto start_blkdone;
+        do_dry;
+        do_blkdone;
+        exit;
       end;
       end;
     BLKDONE:
     BLKDONE:
       begin
       begin
-        start_blkdone:
-        r := Z_STREAM_END;
-        { update pointers and return }
-        s.bitb := b;
-        s.bitk := k;
-        z.avail_in := n;
-        Inc(z.total_in, ptruint(p) - ptruint(z.next_in));
-        z.next_in := p;
-        s.write := q;
-        inflate_blocks := inflate_flush(s,z,r);
+        do_blkdone;
         exit;
         exit;
       end;
       end;
     BLKBAD:
     BLKBAD:

+ 44 - 2
packages/paszlib/src/zdeflate.pas

@@ -1,6 +1,12 @@
 unit ZDeflate;
 unit ZDeflate;
 
 
+{$IFDEF CPUWASM}
+{$DEFINE NOGOTO}
+{$ENDIF}
+
+{$IFNDEF NOGOTO}
 {$goto on}
 {$goto on}
+{$ENDIF}
 
 
 { Orginal: deflate.h -- internal compression state
 { Orginal: deflate.h -- internal compression state
            deflate.c -- compress data using the deflation algorithm
            deflate.c -- compress data using the deflation algorithm
@@ -1206,8 +1212,7 @@ end;
 function longest_match(var s : deflate_state;
 function longest_match(var s : deflate_state;
                        cur_match : IPos  { current match }
                        cur_match : IPos  { current match }
                        ) : cardinal;
                        ) : cardinal;
-label
-  nextstep;
+
 var
 var
   chain_length : cardinal;    { max hash chain length }
   chain_length : cardinal;    { max hash chain length }
   {register} scan : Pbyte;   { current string }
   {register} scan : Pbyte;   { current string }
@@ -1230,6 +1235,19 @@ var
 {$endif}
 {$endif}
 var
 var
   MAX_DIST : cardinal;
   MAX_DIST : cardinal;
+  
+{$IFNDEF NOGOTO}  
+label
+  nextstep;
+{$ELSE}  
+  Procedure DoNextStep; inline;
+  
+  begin
+    cur_match := prev^[cur_match and wmask];
+    dec(chain_length);
+  end;
+{$ENDIF}  
+
 begin
 begin
   chain_length := s.max_chain_length; { max hash chain length }
   chain_length := s.max_chain_length; { max hash chain length }
   scan := @(s.window^[s.strstart]);
   scan := @(s.window^[s.strstart]);
@@ -1307,7 +1325,15 @@ distances are limited to MAX_DIST instead of WSIZE. }
   {$PUSH} {$R-}
   {$PUSH} {$R-}
         if (match[best_len-1]<>scan_end) or
         if (match[best_len-1]<>scan_end) or
            (match^ <> scan_start) then
            (match^ <> scan_start) then
+          {$IFDEF NOGOTO} 
+          begin
+            DoNextStep;
+            Continue;
+          end;  
+          {$ELSE}
           goto nextstep; {continue;}
           goto nextstep; {continue;}
+          {$ENDIF}
+          
   {$POP}
   {$POP}
 
 
         { It is not necessary to compare scan[2] and match[2] since they are
         { It is not necessary to compare scan[2] and match[2] since they are
@@ -1353,11 +1379,25 @@ distances are limited to MAX_DIST instead of WSIZE. }
         if (Pbytearray(match)^[best_len]   <> scan_end) or
         if (Pbytearray(match)^[best_len]   <> scan_end) or
            (Pbytearray(match)^[best_len-1] <> scan_end1) or
            (Pbytearray(match)^[best_len-1] <> scan_end1) or
            (match^ <> scan^) then
            (match^ <> scan^) then
+          {$IFDEF NOGOTO} 
+          begin
+            DoNextStep;
+            Continue;
+          end;
+          {$ELSE}
           goto nextstep; {continue;}
           goto nextstep; {continue;}
+          {$ENDIF}
   {$POP}
   {$POP}
         inc(match);
         inc(match);
         if (match^ <> Pbytearray(scan)^[1]) then
         if (match^ <> Pbytearray(scan)^[1]) then
+          {$IFDEF NOGOTO} 
+          begin
+            DoNextStep;
+            Continue;
+          end;
+          {$ELSE}
           goto nextstep; {continue;}
           goto nextstep; {continue;}
+          {$ENDIF}
 
 
         { The check at best_len-1 can be removed because it will be made
         { The check at best_len-1 can be removed because it will be made
           again later. (This heuristic is not always a win.)
           again later. (This heuristic is not always a win.)
@@ -1411,9 +1451,11 @@ distances are limited to MAX_DIST instead of WSIZE. }
 {$endif}
 {$endif}
 {$pop}
 {$pop}
         end;
         end;
+{$ifndef NOGOTO}        
     nextstep:
     nextstep:
       cur_match := prev^[cur_match and wmask];
       cur_match := prev^[cur_match and wmask];
       dec(chain_length);
       dec(chain_length);
+{$ENDIF}      
     until (cur_match <= limit) or (chain_length = 0);
     until (cur_match <= limit) or (chain_length = 0);
 
 
     if (cardinal(best_len) <= s.lookahead) then
     if (cardinal(best_len) <= s.lookahead) then

+ 13 - 0
packages/paszlib/tests/README.md

@@ -0,0 +1,13 @@
+
+The WebAssembly version of the tczipper test reads/writes temporary files in the current
+directory and in the TMP directory (this is the directory returned by gettempdir). 
+
+You must pre-open these directories so the wasm environment can write in it. 
+
+Using wasmtime this can be done as follows:
+
+wasmtime --dir=.  --dir=/tmp tczipper.wasm
+
+Similarly the testsingle test needs the same 2 directories:
+
+wasmtime --dir=. --dir=/tmp testsingle.wasm

+ 6 - 1
packages/paszlib/tests/tczipper.pp

@@ -257,7 +257,6 @@ begin
     // ignore mess
     // ignore mess
   end;
   end;
   {$ENDIF}
   {$ENDIF}
-
   DestFile:=SysUtils.GetTempFileName('', 'CS2');
   DestFile:=SysUtils.GetTempFileName('', 'CS2');
   z:=TZipper.Create;
   z:=TZipper.Create;
   z.FileName:=DestFile;
   z.FileName:=DestFile;
@@ -454,8 +453,11 @@ begin
       ContentStreams.Add(ContentStream);
       ContentStreams.Add(ContentStream);
       // Start filenames at 1
       // Start filenames at 1
       Zipper.Entries.AddFileEntry(TStringStream(ContentStreams.Items[i]), format('%U',[i+1]));
       Zipper.Entries.AddFileEntry(TStringStream(ContentStreams.Items[i]), format('%U',[i+1]));
+      if (i mod 100)=0 then
+        write(i,' ');
       inc(i);
       inc(i);
     end;
     end;
+    Writeln;
     Zipper.ZipAllFiles;
     Zipper.ZipAllFiles;
     {
     {
     i:=0;
     i:=0;
@@ -493,8 +495,11 @@ begin
       UnzipArchiveFiles.Clear;
       UnzipArchiveFiles.Clear;
       UnzipArchiveFiles.Add(Unzipper.Entries[i].ArchiveFileName);
       UnzipArchiveFiles.Add(Unzipper.Entries[i].ArchiveFileName);
       Unzipper.UnZipFiles(UnzipArchiveFiles);
       Unzipper.UnZipFiles(UnzipArchiveFiles);
+      if (i mod 100)=0 then
+        write(i,' ');
       inc(i);
       inc(i);
     end;
     end;
+    writeln();
   finally
   finally
     CallBackHandler.Free;
     CallBackHandler.Free;
     Unzipper.Free;
     Unzipper.Free;

+ 1 - 0
packages/paszlib/tests/tczstreamseek.pp

@@ -55,4 +55,5 @@ begin
       wasError := True;
       wasError := True;
   end;
   end;
   assert(wasError);
   assert(wasError);
+  writeln('All OK');
 end.
 end.

+ 13 - 0
rtl/inc/objpas.inc

@@ -1241,6 +1241,19 @@ begin
     FCallBack(Self,aMethod,aCount,aData); 
     FCallBack(Self,aMethod,aCount,aData); 
 end;
 end;
 
 
+function TInterfaceThunk.QueryInterface({$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} iid : tguid;out obj) : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
+
+begin
+  result:=longint(E_NOINTERFACE);
+  if (TMethod(FCallBack).Data<>Nil) then
+    // Query the object that created us, this is normally TVirtualInterface
+    // Take care: do not call QueryInterface, that would create a never-ending loop !!
+    if TObject(TMethod(FCallBack).Data).GetInterface(iid,obj) then
+      result:=S_OK;
+  if (Result<>S_OK) then
+    Result:=Inherited QueryInterface(iid,obj);
+end;
+
 function TInterfaceThunk.InterfaceVMTOffset : word;
 function TInterfaceThunk.InterfaceVMTOffset : word;
 
 
 begin
 begin

+ 2 - 1
rtl/inc/objpash.inc

@@ -356,6 +356,7 @@
        Private  
        Private  
          FCallback : TThunkCallback;
          FCallback : TThunkCallback;
        Protected  
        Protected  
+         function QueryInterface({$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} iid : tguid;out obj) : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
          Procedure Thunk(aMethod: Longint; aCount : Longint; aData : PArgData); virtual;
          Procedure Thunk(aMethod: Longint; aCount : Longint; aData : PArgData); virtual;
        Public  
        Public  
          constructor create(aCallBack : TThunkCallback);
          constructor create(aCallBack : TThunkCallback);
@@ -623,4 +624,4 @@ Type
   end;
   end;
   
   
 operator =(Left, Right: TPtrWrapper) c : Boolean;  
 operator =(Left, Right: TPtrWrapper) c : Boolean;  
-operator <>(Left, Right: TPtrWrapper) c : Boolean;
+operator <>(Left, Right: TPtrWrapper) c : Boolean;