瀏覽代碼

+ tempcreate/ref/delete nodes (allows the use of temps in the
resulttype and first pass)
* made handling of read(ln)/write(ln) processor independent
* moved processor independent handling for str and reset/rewrite-typed
from firstpass to resulttype pass
* changed names of helpers in text.inc to be generic for use as
compilerprocs + added "iocheck" directive for most of them
* reading of ordinals is done by procedures instead of functions
because otherwise FPC_IOCHECK overwrote the result before it could
be stored elsewhere (range checking still works)
* compilerprocs can now be used in the system unit before they are
implemented
* added note to errore.msg that booleans can't be read using read/readln

Jonas Maebe 24 年之前
父節點
當前提交
a6cfe4083a
共有 12 個文件被更改,包括 1475 次插入275 次删除
  1. 21 1
      compiler/htypechk.pas
  2. 29 2
      compiler/i386/n386inl.pas
  3. 2 1
      compiler/msg/errore.msg
  4. 231 2
      compiler/nbas.pas
  5. 21 2
      compiler/ncal.pas
  6. 71 2
      compiler/ncgbas.pas
  7. 757 126
      compiler/ninl.pas
  8. 20 1
      compiler/node.pas
  9. 26 3
      compiler/pdecsub.pas
  10. 20 2
      compiler/pstatmnt.pas
  11. 49 1
      rtl/inc/compproc.inc
  12. 228 132
      rtl/inc/text.inc

+ 21 - 1
compiler/htypechk.pas

@@ -758,6 +758,11 @@ implementation
               exit;
             end;
            case hp.nodetype of
+             temprefn :
+               begin
+                 valid_for_assign := true;
+                 exit;
+               end;
              derefn :
                begin
                  gotderef:=true;
@@ -937,7 +942,22 @@ implementation
 end.
 {
   $Log$
-  Revision 1.30  2001-08-06 21:40:46  peter
+  Revision 1.31  2001-08-23 14:28:35  jonas
+    + tempcreate/ref/delete nodes (allows the use of temps in the
+      resulttype and first pass)
+    * made handling of read(ln)/write(ln) processor independent
+    * moved processor independent handling for str and reset/rewrite-typed
+      from firstpass to resulttype pass
+    * changed names of helpers in text.inc to be generic for use as
+      compilerprocs + added "iocheck" directive for most of them
+    * reading of ordinals is done by procedures instead of functions
+      because otherwise FPC_IOCHECK overwrote the result before it could
+      be stored elsewhere (range checking still works)
+    * compilerprocs can now be used in the system unit before they are
+      implemented
+    * added note to errore.msg that booleans can't be read using read/readln
+
+  Revision 1.30  2001/08/06 21:40:46  peter
     * funcret moved from tprocinfo to tprocdef
 
   Revision 1.29  2001/06/04 18:04:36  peter

+ 29 - 2
compiler/i386/n386inl.pas

@@ -79,6 +79,7 @@ implementation
                               TI386INLINENODE
 *****************************************************************************}
 
+{$ifndef hascompilerproc}
     procedure StoreDirectFuncResult(var dest:tnode);
       var
         hp : tnode;
@@ -176,6 +177,7 @@ implementation
         { free used registers }
         del_locref(dest.location);
       end;
+{$endif not hascomppilerproc}
 
     procedure ti386inlinenode.pass_2;
        const
@@ -196,7 +198,7 @@ implementation
          addvalue : longint;
          hp : tnode;
 
-
+{$ifndef hascompilerproc}
       procedure handlereadwrite(doread,doln : boolean);
       { produces code for READ(LN) and WRITE(LN) }
 
@@ -544,6 +546,7 @@ implementation
         myexit:
            dummycoll.free;
         end;
+{$endif not hascomppilerproc}
 
 {$ifndef hascompilerproc}
       procedure handle_str;
@@ -1491,6 +1494,7 @@ implementation
                     end;
                   popusedregisters(pushed);
                end;
+{$ifndef hascompilerproc}
             in_write_x :
               handlereadwrite(false,false);
             in_writeln_x :
@@ -1499,6 +1503,14 @@ implementation
               handlereadwrite(true,false);
             in_readln_x :
               handlereadwrite(true,true);
+{$else hascomppilerproc}
+              in_read_x,
+              in_readln_x,
+              in_write_x,
+              in_writeln_x :
+                { should be removed in the resulttype pass already (JM) }
+                internalerror(200108162);
+{$endif not hascomppilerproc}
             in_str_x_string :
               begin
 {$ifndef hascompilerproc}
@@ -1705,7 +1717,22 @@ begin
 end.
 {
   $Log$
-  Revision 1.18  2001-08-13 15:39:52  jonas
+  Revision 1.19  2001-08-23 14:28:36  jonas
+    + tempcreate/ref/delete nodes (allows the use of temps in the
+      resulttype and first pass)
+    * made handling of read(ln)/write(ln) processor independent
+    * moved processor independent handling for str and reset/rewrite-typed
+      from firstpass to resulttype pass
+    * changed names of helpers in text.inc to be generic for use as
+      compilerprocs + added "iocheck" directive for most of them
+    * reading of ordinals is done by procedures instead of functions
+      because otherwise FPC_IOCHECK overwrote the result before it could
+      be stored elsewhere (range checking still works)
+    * compilerprocs can now be used in the system unit before they are
+      implemented
+    * added note to errore.msg that booleans can't be read using read/readln
+
+  Revision 1.18  2001/08/13 15:39:52  jonas
     * made in_reset_typedfile/in_rewrite_typedfile handling processor
       independent
 

+ 2 - 1
compiler/msg/errore.msg

@@ -1018,7 +1018,8 @@ type_e_succ_and_pred_enums_with_assign_not_possible=04017_E_succ or pred on enum
 type_e_cant_read_write_type=04018_E_Can't read or write variables of this type
 % You are trying to \var{read} or \var{write} a variable from or to a
 % file of type text, which doesn't support that. Only integer types,
-% booleans, reals, pchars and strings can be read from/written to a text file.
+% reals, pchars and strings can be read from/written to a text file.
+% Booleans can only be written to text files.
 type_e_no_readln_writeln_for_typed_file=04019_E_Can't use readln or writeln on typed file
 % \var{readln} and \var{writeln} are only allowed for text files.
 type_e_no_read_write_for_untyped_file=04020_E_Can't use read or write on untyped file.

+ 231 - 2
compiler/nbas.pas

@@ -27,7 +27,7 @@ unit nbas;
 interface
 
     uses
-       aasm,node;
+       aasm,symtype,node,cpubase;
 
     type
        tnothingnode = class(tnode)
@@ -67,12 +67,63 @@ interface
           function det_resulttype:tnode;override;
        end;
 
+       { to allow access to the location by temp references even after the temp has }
+       { already been disposed and to make sure the coherency between temps and     }
+       { temp references is kept after a getcopy                                    }
+       ptempinfo = ^ttempinfo;
+       ttempinfo = record
+         { set to the copy of a tempcreate pnode (if it gets copied) so that the }
+         { refs and deletenode can hook to this copy once they get copied too    }
+         hookoncopy: ptempinfo;
+         ref: treference;
+         restype: ttype;
+         valid: boolean;
+       end;
+
+       { a node which will create a *persistent* temp of a given type with a given size }
+       { (the size is separate to allow creating "void" temps with a custom size)       }
+       ttempcreatenode = class(tnode)
+          size: longint;
+          tempinfo: ptempinfo;
+          constructor create(const _restype: ttype; _size: longint); virtual;
+          function getcopy: tnode; override;
+          function pass_1 : tnode; override;
+          function det_resulttype: tnode; override;
+          function docompare(p: tnode): boolean; override;
+        end;
+
+        { a node which is a reference to a certain temp }
+        ttemprefnode = class(tnode)
+          constructor create(const temp: ttempcreatenode); virtual;
+          function getcopy: tnode; override;
+          function pass_1 : tnode; override;
+          function det_resulttype : tnode; override;
+          function docompare(p: tnode): boolean; override;
+         protected
+          tempinfo: ptempinfo;
+        end;
+
+        { a node which removes a temp }
+        ttempdeletenode = class(tnode)
+          constructor create(const temp: ttempcreatenode);
+          function getcopy: tnode; override;
+          function pass_1: tnode; override;
+          function det_resulttype: tnode; override;
+          function docompare(p: tnode): boolean; override;
+          destructor destroy; override;
+         protected
+          tempinfo: ptempinfo;
+        end;
+
     var
        cnothingnode : class of tnothingnode;
        cerrornode : class of terrornode;
        casmnode : class of tasmnode;
        cstatementnode : class of tstatementnode;
        cblocknode : class of tblocknode;
+       ctempcreatenode : class of ttempcreatenode;
+       ctemprefnode : class of ttemprefnode;
+       ctempdeletenode : class of ttempdeletenode;
 
 implementation
 
@@ -387,16 +438,194 @@ implementation
         docompare := false;
       end;
 
+{*****************************************************************************
+                          TEMPCREATENODE
+*****************************************************************************}
+
+    constructor ttempcreatenode.create(const _restype: ttype; _size: longint);
+      begin
+        inherited create(tempn);
+        size := _size;
+        new(tempinfo);
+        fillchar(tempinfo^,sizeof(tempinfo^),0);
+        tempinfo^.restype := _restype;
+      end;
+
+    function ttempcreatenode.getcopy: tnode;
+      var
+        n: ttempcreatenode;
+      begin
+        n := ttempcreatenode(inherited getcopy);
+        n.size := size;
+        
+        new(n.tempinfo);
+        fillchar(n.tempinfo^,sizeof(n.tempinfo^),0);
+        n.tempinfo^.restype := tempinfo^.restype;
+
+        { signal the temprefs that the temp they point to has been copied, }
+        { so that if the refs get copied as well, they can hook themselves }
+        { to the copy of the temp                                          }
+        tempinfo^.hookoncopy := n.tempinfo;
+
+        result := n;
+      end;
+
+    function ttempcreatenode.pass_1 : tnode;
+      begin
+        result := nil;
+      end;
+
+    function ttempcreatenode.det_resulttype: tnode;
+      begin
+        result := nil;
+        { a tempcreatenode doesn't have a resulttype, only temprefnodes do }
+        resulttype := voidtype;
+      end;
+
+    function ttempcreatenode.docompare(p: tnode): boolean;
+      begin
+        result :=
+          inherited docompare(p) and
+          (ttempcreatenode(p).size = size) and
+          is_equal(ttempcreatenode(p).tempinfo^.restype.def,tempinfo^.restype.def);
+      end;
+
+{*****************************************************************************
+                             TEMPREFNODE
+*****************************************************************************}
+
+    constructor ttemprefnode.create(const temp: ttempcreatenode);
+      begin
+        inherited create(temprefn);
+        tempinfo := temp.tempinfo;
+      end;
+
+    function ttemprefnode.getcopy: tnode;
+      var
+        n: ttemprefnode;
+      begin
+        n := ttemprefnode(inherited getcopy);
+
+        if assigned(tempinfo^.hookoncopy) then
+          { if the temp has been copied, assume it becomes a new }
+          { temp which has to be hooked by the copied reference  }
+          begin
+            { hook the ref to the copied temp }
+            n.tempinfo := tempinfo^.hookoncopy;
+          end
+        else
+          { if the temp we refer to hasn't been copied, assume }
+          { we're just a new reference to that temp            }
+          begin
+            n.tempinfo := tempinfo;
+          end;
+
+        result := n;
+      end;
+
+    function ttemprefnode.pass_1 : tnode;
+      begin
+        result := nil;
+      end;
+
+    function ttemprefnode.det_resulttype: tnode;
+      begin
+        { check if the temp is already resulttype passed }
+        if not assigned(tempinfo^.restype.def) then
+          internalerror(200108233);
+        result := nil;
+        resulttype := tempinfo^.restype;
+      end;
+
+    function ttemprefnode.docompare(p: tnode): boolean;
+      begin
+        result :=
+          inherited docompare(p) and
+          (ttemprefnode(p).tempinfo = tempinfo);
+      end;
+
+{*****************************************************************************
+                             TEMPDELETENODE
+*****************************************************************************}
+
+    constructor ttempdeletenode.create(const temp: ttempcreatenode);
+      begin
+        inherited create(temprefn);
+        tempinfo := temp.tempinfo;
+      end;
+
+    function ttempdeletenode.getcopy: tnode;
+      var
+        n: ttempdeletenode;
+      begin
+        n := ttempdeletenode(inherited getcopy);
+
+        if assigned(tempinfo^.hookoncopy) then
+          { if the temp has been copied, assume it becomes a new }
+          { temp which has to be hooked by the copied deletenode }
+          begin
+            { hook the tempdeletenode to the copied temp }
+            n.tempinfo := tempinfo^.hookoncopy;
+          end
+        else
+          { if the temp we refer to hasn't been copied, we have a }
+          { problem since that means we now have two delete nodes }
+          { for one temp                                          }
+          internalerror(200108234);        
+        result := n;
+      end;
+
+    function ttempdeletenode.pass_1 : tnode;
+      begin
+        result := nil;
+      end;
+
+    function ttempdeletenode.det_resulttype: tnode;
+      begin
+        result := nil;
+        resulttype := voidtype;
+      end;
+
+    function ttempdeletenode.docompare(p: tnode): boolean;
+      begin
+        result :=
+          inherited docompare(p) and
+          (ttemprefnode(p).tempinfo = tempinfo);
+      end;
+      
+    destructor ttempdeletenode.destroy;
+      begin
+        dispose(tempinfo);
+      end;
+
 begin
    cnothingnode:=tnothingnode;
    cerrornode:=terrornode;
    casmnode:=tasmnode;
    cstatementnode:=tstatementnode;
    cblocknode:=tblocknode;
+   ctempcreatenode:=ttempcreatenode;
+   ctemprefnode:=ttemprefnode;
+   ctempdeletenode:=ttempdeletenode;
 end.
 {
   $Log$
-  Revision 1.13  2001-08-06 21:40:46  peter
+  Revision 1.14  2001-08-23 14:28:35  jonas
+    + tempcreate/ref/delete nodes (allows the use of temps in the
+      resulttype and first pass)
+    * made handling of read(ln)/write(ln) processor independent
+    * moved processor independent handling for str and reset/rewrite-typed
+      from firstpass to resulttype pass
+    * changed names of helpers in text.inc to be generic for use as
+      compilerprocs + added "iocheck" directive for most of them
+    * reading of ordinals is done by procedures instead of functions
+      because otherwise FPC_IOCHECK overwrote the result before it could
+      be stored elsewhere (range checking still works)
+    * compilerprocs can now be used in the system unit before they are
+      implemented
+    * added note to errore.msg that booleans can't be read using read/readln
+
+  Revision 1.13  2001/08/06 21:40:46  peter
     * funcret moved from tprocinfo to tprocdef
 
   Revision 1.12  2001/06/11 17:41:12  jonas

+ 21 - 2
compiler/ncal.pas

@@ -551,7 +551,11 @@ implementation
              symowner := systemunit;
            end
          else
-           searchsym(name,srsym,symowner);
+           begin
+             searchsym(name,srsym,symowner);
+             if not assigned(srsym) then
+               searchsym(upper(name),srsym,symowner);
+           end;
          if not assigned(srsym) or
             (srsym.typ <> procsym) then
            internalerror(200107271);
@@ -1687,7 +1691,22 @@ begin
 end.
 {
   $Log$
-  Revision 1.42  2001-08-19 21:11:20  florian
+  Revision 1.43  2001-08-23 14:28:35  jonas
+    + tempcreate/ref/delete nodes (allows the use of temps in the
+      resulttype and first pass)
+    * made handling of read(ln)/write(ln) processor independent
+    * moved processor independent handling for str and reset/rewrite-typed
+      from firstpass to resulttype pass
+    * changed names of helpers in text.inc to be generic for use as
+      compilerprocs + added "iocheck" directive for most of them
+    * reading of ordinals is done by procedures instead of functions
+      because otherwise FPC_IOCHECK overwrote the result before it could
+      be stored elsewhere (range checking still works)
+    * compilerprocs can now be used in the system unit before they are
+      implemented
+    * added note to errore.msg that booleans can't be read using read/readln
+
+  Revision 1.42  2001/08/19 21:11:20  florian
     * some bugs fix:
       - overload; with external procedures fixed
       - better selection of routine to do an overloaded

+ 71 - 2
compiler/ncgbas.pas

@@ -45,6 +45,18 @@ interface
        tcgblocknode = class(tblocknode)
           procedure pass_2;override;
        end;
+       
+       tcgtempcreatenode = class(ttempcreatenode)
+          procedure pass_2;override;
+       end;
+
+       tcgtemprefnode = class(ttemprefnode)
+          procedure pass_2;override;
+       end;
+
+       tcgtempdeletenode = class(ttempdeletenode)
+          procedure pass_2;override;
+       end;
 
   implementation
 
@@ -63,7 +75,7 @@ interface
 {$ifdef i386}
       ,cgai386
 {$endif}
-      ,tgcpu
+      ,tgcpu,temp_gen
       ;
 {*****************************************************************************
                                  TNOTHING
@@ -219,16 +231,73 @@ interface
          secondpass(left);
       end;
 
+{*****************************************************************************
+                          TTEMPCREATENODE
+*****************************************************************************}
+
+    procedure tcgtempcreatenode.pass_2;
+      begin
+        { if we're secondpassing the same tcgtempcreatenode twice, we have a bug }
+        if tempinfo^.valid then
+          internalerror(200108222);
+
+        { get a (persistent) temp }
+        gettempofsizereferencepersistant(size,tempinfo^.ref);
+        tempinfo^.valid := true;
+      end;
+
+
+{*****************************************************************************
+                             TTEMPREFNODE
+*****************************************************************************}
+
+    procedure tcgtemprefnode.pass_2;
+      begin
+        { check if the temp is valid }
+        if not tempinfo^.valid then
+          internalerror(200108231);
+        { set the temp's location }
+        location.loc := LOC_REFERENCE;
+        location.reference := tempinfo^.ref;
+      end;
+
+{*****************************************************************************
+                           TTEMPDELETENODE
+*****************************************************************************}
+
+    procedure tcgtempdeletenode.pass_2;
+      begin
+        ungetpersistanttempreference(tempinfo^.ref);
+      end;
+
 
 begin
    cnothingnode:=tcgnothingnode;
    casmnode:=tcgasmnode;
    cstatementnode:=tcgstatementnode;
    cblocknode:=tcgblocknode;
+   ctempcreatenode:=tcgtempcreatenode;
+   ctemprefnode:=tcgtemprefnode;
+   ctempdeletenode:=tcgtempdeletenode;
 end.
 {
   $Log$
-  Revision 1.4  2001-06-02 19:22:15  peter
+  Revision 1.5  2001-08-23 14:28:35  jonas
+    + tempcreate/ref/delete nodes (allows the use of temps in the
+      resulttype and first pass)
+    * made handling of read(ln)/write(ln) processor independent
+    * moved processor independent handling for str and reset/rewrite-typed
+      from firstpass to resulttype pass
+    * changed names of helpers in text.inc to be generic for use as
+      compilerprocs + added "iocheck" directive for most of them
+    * reading of ordinals is done by procedures instead of functions
+      because otherwise FPC_IOCHECK overwrote the result before it could
+      be stored elsewhere (range checking still works)
+    * compilerprocs can now be used in the system unit before they are
+      implemented
+    * added note to errore.msg that booleans can't be read using read/readln
+
+  Revision 1.4  2001/06/02 19:22:15  peter
     * refs count for relabeled asmsymbols fixed
 
   Revision 1.3  2001/05/18 22:31:06  peter

+ 757 - 126
compiler/ninl.pas

@@ -41,8 +41,9 @@ interface
           function docompare(p: tnode): boolean; override;
 {$ifdef hascompilerproc}
         private
-          function str_pass_1: tnode;
-          function reset_rewrite_typed_pass_1: tnode;
+          function handle_str: tnode;
+          function handle_reset_rewrite_typed: tnode;
+          function handle_read_write: tnode;
 {$endif hascompilerproc}
        end;
 
@@ -55,10 +56,10 @@ implementation
 
     uses
       verbose,globals,systems,
-      globtype,
-      symconst,symtype,symdef,symsym,symtable,types,
+      globtype, cutils, aasm,
+      symbase,symconst,symtype,symdef,symsym,symtable,types,
       pass_1,
-      ncal,ncon,ncnv,nadd,nld,nbas,
+      ncal,ncon,ncnv,nadd,nld,nbas,nflw,nmem,
       cpubase,hcodegen,tgcpu
 {$ifdef newcg}
       ,cgbase
@@ -95,6 +96,720 @@ implementation
       end;
 
 
+{$ifdef hascompilerproc}
+    function tinlinenode.handle_str : tnode;
+      var
+        lenpara,
+        fracpara,
+        newparas,
+        dest,
+        source  : tcallparanode;
+        newnode : tnode;
+        len,
+        fraclen : longint;
+        procname: string;
+        is_real : boolean;
+
+      begin
+        result := cerrornode.create;
+        
+        { make sure we got at least two parameters (if we got only one, }
+        { this parameter may not be encapsulated in a callparan)        }
+        if not assigned(left) or
+           (left.nodetype <> callparan) then
+          exit;
+
+        { get destination string }
+        dest := tcallparanode(left);
+
+        { get source para (number) }
+        source := dest;
+        while assigned(source.right) do
+          source := tcallparanode(source.right);
+        is_real := source.resulttype.def.deftype = floatdef;
+        
+        if not assigned(dest) or
+           (dest.left.resulttype.def.deftype<>stringdef) or
+           not(is_real or
+               (source.left.resulttype.def.deftype = orddef)) then
+          begin
+            { the parser will give this message already because we }
+            { return an errornode (JM)                             }
+            { CGMessagePos(fileinfo,cg_e_illegal_expression);      }
+            exit;
+          end;
+
+        { get len/frac parameters }
+        lenpara := nil;
+        fracpara := nil;
+        if (cpf_is_colon_para in tcallparanode(dest.right).callparaflags) then
+          begin
+            lenpara := tcallparanode(dest.right);
+            
+            { we can let the callnode do the type checking of these parameters too, }
+            { but then the error messages aren't as nice                            }
+            if not is_integer(lenpara.resulttype.def) then
+              begin
+                CGMessagePos1(lenpara.fileinfo,
+                  type_e_integer_expr_expected,lenpara.resulttype.def.typename);
+                exit;
+              end;
+            if (cpf_is_colon_para in tcallparanode(lenpara.right).callparaflags) then
+              begin
+                { parameters are in reverse order! }
+                fracpara := lenpara;
+                lenpara := tcallparanode(lenpara.right);
+                if not is_real then
+                  begin
+                    CGMessagePos(lenpara.fileinfo,parser_e_illegal_colon_qualifier);
+                    exit
+                  end;
+                if not is_integer(lenpara.resulttype.def) then
+                  begin
+                    CGMessagePos1(lenpara.fileinfo,
+                      type_e_integer_expr_expected,lenpara.resulttype.def.typename);
+                    exit;
+                  end;
+              end;
+          end;
+
+        { generate the parameter list for the compilerproc }
+        newparas := dest;
+
+        { if we have a float parameter, insert the realtype, len and fracpara parameters }
+        if is_real then
+          begin
+            { insert realtype parameter }
+            newparas.right := ccallparanode.create(cordconstnode.create(
+              ord(tfloatdef(source.left.resulttype.def).typ),s32bittype),newparas.right);
+            { if necessary, insert a fraction parameter }
+            if not assigned(fracpara) then
+              begin
+                tcallparanode(newparas.right).right := ccallparanode.create(
+                  cordconstnode.create(-1,s32bittype),tcallparanode(newparas.right).right);
+                fracpara := tcallparanode(tcallparanode(newparas.right).right);
+              end;
+            { if necessary, insert a length para }
+            if not assigned(lenpara) then
+              fracpara.right := ccallparanode.create(cordconstnode.create(-32767,s32bittype),
+                fracpara.right);
+          end
+        else
+          { for a normal parameter, insert a only length parameter if one is missing }
+          if not assigned(lenpara) then
+            newparas.right := ccallparanode.create(cordconstnode.create(-1,s32bittype),
+              newparas.right);
+        
+        { remove the parameters from the original node so they won't get disposed, }
+        { since they're reused                                                     }
+        left := nil;
+
+        { create procedure name }
+        procname := 'fpc_' + lower(tstringdef(dest.resulttype.def).stringtypname)+'_';
+        if is_real then
+          procname := procname + 'float'
+        else
+          case torddef(dest.resulttype.def).typ of
+            u32bit:
+              procname := procname + 'cardinal';
+            u64bit:
+              procname := procname + 'qword';
+            s64bit:
+              procname := procname + 'int64';
+            else
+              procname := procname + 'longint';
+          end;
+
+        { create the call node, }
+        newnode := ccallnode.createintern(procname,newparas);
+        { resulttypepass it }
+        resulttypepass(newnode);
+
+        { and return it (but first free the errornode we generated in the beginning) }
+        result.free;
+        result := newnode;
+      end;
+      
+      
+    function tinlinenode.handle_reset_rewrite_typed: tnode;
+      begin
+        { since this is a "in_xxxx_typedfile" node, we can be sure we have  }
+        { a typed file as argument and we don't have to check it again (JM) }
+
+        { add the recsize parameter }
+        { note: for some reason, the parameter of intern procedures with only one }
+        {   parameter is gets lifted out of its original tcallparanode (see round }
+        {   line 1306 of ncal.pas), so recreate a tcallparanode here (JM)         }
+        left := ccallparanode.create(cordconstnode.create(
+          tfiledef(left.resulttype.def).typedfiletype.def.size,s32bittype),
+          ccallparanode.create(left,nil));
+        { create the correct call }
+        if inlinenumber=in_reset_typedfile then
+          result := ccallnode.createintern('fpc_reset_typed',left)
+        else
+          result := ccallnode.createintern('fpc_rewrite_typed',left);
+        firstpass(result);
+        { make sure left doesn't get disposed, since we use it in the new call }
+        left := nil;
+      end;
+
+
+    function tinlinenode.handle_read_write: tnode;
+
+      function reverseparameters(p: tnode): tnode;
+        var
+          hp1, hp2: tnode;
+        begin
+          hp1:=nil;
+          while assigned(p) do
+            begin
+               { pull out }
+               hp2:=p;
+               p:=tcallparanode(p).right;
+               { pull in }
+               tcallparanode(hp2).right:=hp1;
+               hp1:=hp2;
+            end;
+          reverseparameters:=hp1;
+        end;
+
+
+      const
+        procnames: array[boolean,boolean] of string[11] =
+          (('write_text_','read_text_'),('typed_write','typed_read'));
+      
+      var
+        filepara,
+        lenpara,
+        fracpara,
+        nextpara,
+        para          : tcallparanode;
+        newstatement  : tstatementnode;
+        newblock      : tblocknode;
+        p1            : tnode;
+        filetemp,
+        temp          : ttempcreatenode;
+        tempref       : ttemprefnode;
+        procprefix,
+        name          : string[31];
+        srsym         : tsym;
+        tempowner     : tsymtable;
+        restype       : ^ttype;
+        is_typed,
+        do_read,
+        is_real,
+        error_para,
+        found_error,
+        is_ordinal   : boolean;
+      begin
+        filepara := nil;
+        is_typed := false;
+        filetemp := nil;
+        do_read := inlinenumber in [in_read_x,in_readln_x];
+        { if we fail, we can quickly exit this way. We must generate something }
+        { instead of the inline node, because firstpass will bomb with an      }
+        { internalerror if it encounters a read/write                          }
+        result := cerrornode.create;
+
+        { reverse the parameters (needed to get the colon parameters in the }
+        { correct order when processing write(ln)                           }
+        left := reverseparameters(left);
+
+        if assigned(left) then
+          begin
+            { check if we have a file parameter and if yes, what kind it is }
+            filepara := tcallparanode(left);
+
+            if (filepara.resulttype.def.deftype=filedef) then
+              begin
+                if (tfiledef(filepara.resulttype.def).filetyp=ft_untyped) then
+                  begin
+                    CGMessagePos(fileinfo,type_e_no_read_write_for_untyped_file);
+                    exit;
+                  end
+                else 
+                  begin
+                    if (tfiledef(filepara.resulttype.def).filetyp=ft_typed) then
+                      begin
+                        if (inlinenumber in [in_readln_x,in_writeln_x]) then
+                          begin
+                            CGMessagePos(fileinfo,type_e_no_readln_writeln_for_typed_file);
+                            exit;
+                          end;
+                        is_typed := true;
+                      end
+                  end;
+                { the file para is a var parameter, but it must be valid already }
+                set_varstate(filepara,true);
+              end
+            else
+              filepara := nil;
+          end;
+
+        { create a blocknode in which the successive write/read statements will be  }
+        { put, since they belong together. Also create a dummy statement already to }
+        { make inserting of additional statements easier                            }
+        newstatement := cstatementnode.create(nil,cnothingnode.create);
+        newblock := cblocknode.create(newstatement);
+
+        { if we don't have a filepara, create one containing the default }
+        if not assigned(filepara) then
+          begin
+
+            { create a loadnode for the standard input/output handle }
+            if do_read then
+              name := 'INPUT'
+            else
+              name := 'OUTPUT';
+
+            { if we are compiling the system unit, the systemunit symtable is nil. }
+            { however, if we aren't compiling the system unit, another unit could  }
+            { also have defined the INPUT or OUTPUT symbols. Therefore we need the }
+            { separate cases (JM)                                                  }
+            if not (cs_compilesystem in aktmoduleswitches) then
+              begin
+                srsym := searchsymonlyin(systemunit,name);
+                tempowner := systemunit;
+              end
+            else
+              searchsym(name,srsym,tempowner);
+
+            if not assigned(srsym) then
+              internalerror(200108141);
+
+            { create the file parameter }
+            filepara := ccallparanode.create(cloadnode.create(srsym,tempowner),nil);
+          end
+        else
+          { remove filepara from the parameter chain }
+          begin
+            left := filepara.right;
+            filepara.right := nil;
+            { check if we should make a temp to store the result of a complex }
+            { expression (better heuristics, anyone?) (JM)                    }
+            if (filepara.left.nodetype <> loadn) then
+              begin
+                { create a temp which will hold a pointer to the file }
+                filetemp := ctempcreatenode.create(voidpointertype,voidpointertype.def.size);
+
+                { add it to the statements }
+                newstatement.left := cstatementnode.create(nil,filetemp);
+                newstatement := tstatementnode(newstatement.left);
+
+                { make sure the resulttype of the temp (and as such of the }
+                { temprefs coming after it) is set (necessary because the  }
+                { temprefs will be part of the filepara, of which we need  }
+                { the resulttype later on and temprefs can only be         }
+                { resulttypepassed if the resulttype of the temp is known) }
+                resulttypepass(filetemp);
+
+                { assign the address of the file to the temp }
+                newstatement.left := cstatementnode.create(nil,
+                  cassignmentnode.create(ctemprefnode.create(filetemp),
+                    caddrnode.create(filepara.left)));
+                newstatement := tstatementnode(newstatement.left);
+                resulttypepass(newstatement.right);
+                { create a new fileparameter as follows: file_type(temp^)    }
+                { (so that we pass the value and not the address of the temp }
+                { to the read/write routine)                                 }
+                nextpara := ccallparanode.create(ctypeconvnode.create(
+                  cderefnode.create(ctemprefnode.create(filetemp)),filepara.left.resulttype),nil);
+                { make sure the type conversion is explicit, otherwise this }
+                { typecast won't work                                       }
+                nextpara.left.toggleflag(nf_explizit);
+
+                { replace the old file para with the new one }
+                filepara.left := nil;
+                filepara.free;
+                filepara := nextpara;
+
+                { the resulttype of the filepara must be set since it's }
+                { used below                                            }
+                filepara.get_paratype;
+              end;
+          end;
+
+        { now, filepara is nowhere referenced anymore, so we can safely dispose it }
+        { if something goes wrong or at the end of the procedure                   }
+
+        { choose the correct procedure prefix }
+        procprefix := 'fpc_'+procnames[is_typed,do_read];
+
+        { we're going to reuse the paranodes, so make sure they don't get freed }
+        { twice                                                                 }
+        para := tcallparanode(left);
+        left := nil;
+
+        { no errors found yet... }
+        found_error := false;
+
+        if is_typed then
+          begin
+            { add the typesize to the filepara }
+            filepara.right := ccallparanode.create(cordconstnode.create(
+              tfiledef(filepara.resulttype.def).typedfiletype.def.size,s32bittype),nil);
+
+            { check for "no parameters" (you need at least one extra para for typed files) }
+            if not assigned(para) then
+              begin
+                CGMessage(parser_e_wrong_parameter_size);
+                found_error := true;
+              end;
+
+            { process all parameters }
+            while assigned(para) do
+              begin
+                { check if valid parameter }
+                if para.left.nodetype=typen then
+                  begin
+                    CGMessagePos(para.left.fileinfo,type_e_cant_read_write_type);
+                    found_error := true;
+                  end;
+
+                if not is_equal(para.left.resulttype.def,tfiledef(filepara.resulttype.def).typedfiletype.def) then
+                  begin
+                    CGMessagePos(para.left.fileinfo,type_e_mismatch);
+                    found_error := true;
+                  end;
+
+                if assigned(para.right) and
+                   (cpf_is_colon_para in tcallparanode(para.right).callparaflags) then
+                  begin
+                    CGMessagePos(para.right.fileinfo,parser_e_illegal_colon_qualifier);
+
+                    { skip all colon para's }
+                    nextpara := tcallparanode(tcallparanode(para.right).right);
+                    while assigned(nextpara) and
+                          (cpf_is_colon_para in nextpara.callparaflags) do
+                      nextpara := tcallparanode(nextpara.right);
+
+                    found_error := true;
+                  end
+                else
+                  { get next parameter }
+                  nextpara := tcallparanode(para.right);
+
+                { add fileparameter }
+                para.right := filepara.getcopy;
+
+                { create call statment                                             }
+                { since the parameters are in the correct order, we have to insert }
+                { the statements always at the end of the current block            }
+                newstatement.left := cstatementnode.create(nil,
+                  ccallnode.createintern(procprefix,para));
+                newstatement := tstatementnode(newstatement.left);
+
+                { process next parameter }
+                para := nextpara;
+              end;
+
+            { free the file parameter }
+            filepara.free;
+          end
+        else
+          { text write }
+          begin
+            while assigned(para) do
+              begin
+                { is this parameter faulty? }
+                error_para := false;
+                { is this parameter an ordinal? }
+                is_ordinal := false;
+                { is this parameter a real? }
+                is_real:=false;
+
+                { can't read/write types }
+                if para.left.nodetype=typen then
+                  begin
+                    CGMessagePos(para.fileinfo,type_e_cant_read_write_type);
+                    error_para := true;
+                  end;
+
+                { support writeln(procvar) }
+                if (para.left.resulttype.def.deftype=procvardef) then
+                  begin
+                    p1:=ccallnode.create(nil,nil,nil,nil);
+                    tcallnode(p1).set_procvar(para.left);
+                    resulttypepass(p1);
+                    para.left:=p1;
+                  end;
+
+                case para.left.resulttype.def.deftype of
+                  stringdef :
+                    begin
+                      name := procprefix+lower(tstringdef(para.left.resulttype.def).stringtypname);
+                    end;
+                  pointerdef :
+                    begin
+                      if not is_pchar(para.left.resulttype.def) then
+                        begin
+                          CGMessagePos(para.fileinfo,type_e_cant_read_write_type);
+                          error_para := true;
+                        end
+                      else
+                        name := procprefix+'pchar_as_pointer';
+                    end;
+                  floatdef :
+                    begin
+                      is_real:=true;
+                      name := procprefix+'float';
+                    end;
+                  orddef :
+                    begin
+                      is_ordinal := true;
+                      case torddef(para.left.resulttype.def).typ of
+                        s8bit,s16bit,s32bit :
+                          name := procprefix+'sint';
+                        u8bit,u16bit,u32bit :
+                          name := procprefix+'uint';
+                        uchar :
+                          name := procprefix+'char';
+                        uwidechar :
+                          name := procprefix+'widechar';
+                        s64bit :
+                          name := procprefix+'int64';
+                        u64bit :
+                          name := procprefix+'qword';
+                        bool8bit,
+                        bool16bit,
+                        bool32bit :
+                          begin
+                            if do_read then
+                              begin
+                                CGMessagePos(para.fileinfo,type_e_cant_read_write_type);
+                                error_para := true;
+                              end
+                            else
+                              name := procprefix+'boolean'
+                            end
+                        else
+                          begin
+                            CGMessagePos(para.fileinfo,type_e_cant_read_write_type);
+                            error_para := true;
+                          end;
+                      end;
+                    end;
+                  arraydef :
+                    begin
+                      if is_chararray(para.left.resulttype.def) then
+                        name := procprefix+'pchar_as_array'
+                      else
+                        begin
+                          CGMessagePos(para.fileinfo,type_e_cant_read_write_type);
+                          error_para := true;
+                        end
+                    end
+                  else
+                    begin
+                      CGMessagePos(para.fileinfo,type_e_cant_read_write_type);
+                      error_para := true;
+                    end
+                end;
+
+                { check for length/fractional colon para's }
+                fracpara := nil;
+                lenpara := nil;
+                if assigned(para.right) and
+                   (cpf_is_colon_para in tcallparanode(para.right).callparaflags) then
+                  begin
+                    lenpara := tcallparanode(para.right);
+                    if assigned(lenpara.right) and
+                       (cpf_is_colon_para in tcallparanode(lenpara.right).callparaflags) then
+                      fracpara:=tcallparanode(lenpara.right);
+                  end;
+                { get the next parameter now already, because we're going }
+                { to muck around with the pointers                        }
+                if assigned(fracpara) then
+                  nextpara := tcallparanode(fracpara.right)
+                else if assigned(lenpara) then
+                  nextpara := tcallparanode(lenpara.right)
+                else
+                  nextpara := tcallparanode(para.right);
+
+                { check if a fracpara is allowed }
+                if assigned(fracpara) and not is_real then
+                  begin
+                    CGMessagePos(fracpara.fileinfo,parser_e_illegal_colon_qualifier);
+                    error_para := true;
+                  end
+                else if assigned(lenpara) and do_read then
+                  begin
+                    { I think this is already filtered out by parsing, but I'm not sure (JM) }
+                    CGMessagePos(lenpara.fileinfo,parser_e_illegal_colon_qualifier);
+                    error_para := true;
+                  end;
+
+                { adjust found_error }
+                found_error := found_error or error_para;
+
+                if not error_para then
+                  begin
+                    { create dummy frac/len para's if necessary }
+                    if not do_read then
+                      begin
+                        { difference in default value for floats and the rest :( }
+                        if not is_real then
+                          begin
+                            if not assigned(lenpara) then
+                              lenpara := ccallparanode.create(cordconstnode.create(0,s32bittype),nil)
+                            else
+                              { make sure we don't pass the successive }
+                              { parameters too. We also already have a }
+                              { reference to the next parameter in     }
+                              { nextpara                               }
+                              lenpara.right := nil;
+                          end
+                        else
+                          begin
+                            if not assigned(lenpara) then
+                              lenpara := ccallparanode.create(
+                                cordconstnode.create(-32767,s32bittype),nil);
+                            { also create a default fracpara if necessary }
+                            if not assigned(fracpara) then
+                              fracpara := ccallparanode.create(
+                                cordconstnode.create(-1,s32bittype),nil);
+                            { add it to the lenpara }
+                            lenpara.right := fracpara;
+                            { and add the realtype para (this also removes the link }
+                            { to any parameters coming after it)                    }
+                            fracpara.right := ccallparanode.create(
+                                cordconstnode.create(ord(tfloatdef(para.left.resulttype.def).typ),
+                                s32bittype),nil);
+                          end;
+                      end;
+
+                    if do_read and
+                      ((is_ordinal and
+                        (torddef(para.left.resulttype.def).typ in [s8bit,s16bit,u8bit,u16bit])
+                       ) or
+                       (is_real and
+                        not is_equal(para.left.resulttype.def,pbestrealtype^.def)
+                       )
+                      ) then
+                      { special handling of reading small numbers, because the helpers  }
+                      { expect a longint/card/bestreal var parameter. Use a temp. can't }
+                      { use functions because then the call to FPC_IOCHECK destroys     }
+                      { their result before we can store it                             }
+                      begin
+                        { get the resulttype of the var parameter of the helper }
+                        if is_real then
+                          restype := pbestrealtype
+                        else if is_signed(para.left.resulttype.def) then
+                          restype := @s32bittype
+                        else
+                          restype := @u32bittype;
+
+                        { create the parameter list: the temp ... }
+                        temp := ctempcreatenode.create(restype^,restype^.def.size);
+                        newstatement.left := cstatementnode.create(nil,temp);
+                        newstatement := tstatementnode(newstatement.left);
+
+                        { ... and the file }
+                        p1 := ccallparanode.create(ctemprefnode.create(temp),
+                          filepara.getcopy);
+
+                        { create the call to the helper }
+                        newstatement.left := cstatementnode.create(nil,
+                          ccallnode.createintern(name,tcallparanode(p1)));
+                        newstatement := tstatementnode(newstatement.left);
+
+                        { assign the result to the original var (this automatically }
+                        { takes care of range checking)                             }
+                        newstatement.left := cstatementnode.create(nil,
+                          cassignmentnode.create(para.left,
+                           ctemprefnode.create(temp)));
+                        newstatement := tstatementnode(newstatement.left);
+
+                        { release the temp location }
+                        newstatement.left := cstatementnode.create(nil,
+                          ctempdeletenode.create(temp));
+                        newstatement := tstatementnode(newstatement.left);
+
+                        { statement of para is used }
+                        para.left := nil;
+
+                        { free the enclosing tcallparanode, but not the }
+                        { parameters coming after it                    }
+                        para.right := nil;
+                        para.free;
+                      end
+                    else
+                      { read of non s/u-8/16bit, or a write }
+                      begin
+                        { add the filepara to the current parameter }
+                        para.right := filepara.getcopy;
+                        { add the lenpara (fracpara and realtype are already linked }
+                        { with it if necessary)                                     }
+                        tcallparanode(para.right).right := lenpara;
+                        { create the call statement }
+                        newstatement.left := cstatementnode.create(nil,
+                          ccallnode.createintern(name,para));
+                        newstatement := tstatementnode(newstatement.left);
+                      end
+                  end
+                else
+                  { error_para = true }
+                  begin
+                    { free the parameter, since it isn't referenced anywhere anymore }
+                    para.right := nil;
+                    para.free;
+                    if assigned(lenpara) then
+                      begin
+                        lenpara.right := nil;
+                        lenpara.free;
+                      end;
+                    if assigned(fracpara) then
+                      begin
+                        fracpara.right := nil;
+                        fracpara.free;
+                      end;
+                  end;
+
+                { process next parameter }
+                para := nextpara;
+              end;
+
+            { if no error, add the write(ln)/read(ln) end calls }
+            if not found_error then
+              begin
+                case inlinenumber of
+                  in_read_x:
+                    newstatement.left := ccallnode.createintern('fpc_read_end',filepara);
+                  in_write_x:
+                    newstatement.left := ccallnode.createintern('fpc_write_end',filepara);
+                  in_readln_x:
+                    newstatement.left := ccallnode.createintern('fpc_readln_end',filepara);
+                  in_writeln_x:
+                    newstatement.left := ccallnode.createintern('fpc_writeln_end',filepara);
+                end;
+                newstatement.left := cstatementnode.create(nil,newstatement.left);
+                newstatement := tstatementnode(newstatement.left);
+              end;
+          end;
+
+          { if we found an error, simply delete the generated blocknode }
+          if found_error then
+            newblock.free
+          else
+            begin
+              { deallocate the temp for the file para if we used one }
+              if assigned(filetemp) then
+                begin
+                  newstatement.left := cstatementnode.create(nil,
+                    ctempdeletenode.create(filetemp));
+                  newstatement := tstatementnode(newstatement.left);
+                end;
+              { otherwise return the newly generated block of instructions, }
+              { but first free the errornode we generated at the beginning }
+              result.free;
+              resulttypepass(newblock);
+              result := newblock
+            end;
+      end;
+{$endif hascompilerproc}
+
+
+
     function tinlinenode.det_resulttype:tnode;
 
         function do_lowhigh(const t:ttype) : tnode;
@@ -768,6 +1483,9 @@ implementation
               in_write_x,
               in_writeln_x :
                 begin
+{$ifdef hascompilerproc}
+                  result := handle_read_write;
+{$else hascompilerproc}
                   resulttype:=voidtype;
                { we must know if it is a typed file or not }
                { but we must first do the firstpass for it }
@@ -941,8 +1659,8 @@ implementation
                       exit;
                     set_varstate(left,true);
                  end;
+{$endif hascompilerproc}
                 end;
-
               in_settextbuf_file_x :
                 begin
                   resulttype:=voidtype;
@@ -959,12 +1677,19 @@ implementation
               in_reset_typedfile,
               in_rewrite_typedfile :
                 begin
+{$ifdef hascompilerproc}
+                  result := handle_reset_rewrite_typed;
+{$else hascompilerproc}
                   set_varstate(left,true);
                   resulttype:=voidtype;
+{$endif hascompilerproc}
                 end;
 
               in_str_x_string :
                 begin
+{$ifdef hascompilerproc}
+                  result := handle_str;
+{$else hascompilerproc}
                   resulttype:=voidtype;
                   set_varstate(left,false);
               { remove warning when result is passed }
@@ -978,13 +1703,11 @@ implementation
                 CGMessage(cg_e_illegal_expression);
               { we need a var parameter }
               valid_for_var(tcallparanode(hp).left);
-{$ifndef hascompilerproc}
               { with compilerproc's, this is not necessary anymore, the callnode }
               { will convert it to an openstring itself if necessary (JM)        }
               { generate the high() value for the shortstring }
               if is_shortstring(tcallparanode(hp).left.resulttype.def) then
                 tcallparanode(hp).gen_high_tree(true);
-{$endif not hascompilerproc}
               { !!!! check length of string }
               while assigned(tcallparanode(hp).right) do
                 hp:=tcallparanode(hp).right;
@@ -1044,6 +1767,7 @@ implementation
                        CGMessage(parser_e_illegal_colon_qualifier);
                     end;
                 end;
+{$endif not hascompilerproc}
                 end;
 
               in_val_x :
@@ -1388,120 +2112,6 @@ implementation
 {$maxfpuregisters 0}
 {$endif fpc}
 
-{$ifdef hascompilerproc}
-    function tinlinenode.str_pass_1 : tnode;
-      var
-        lenpara,
-        fracpara,
-        newparas,
-        dest,
-        source  : tcallparanode;
-        newnode : tnode;
-        len,
-        fraclen : longint;
-        procname: string;
-        is_real : boolean;
-
-      begin
-        { get destination string }
-        dest := tcallparanode(left);
-
-        { get source para (number) }
-        source := dest;
-        while assigned(source.right) do
-          source := tcallparanode(source.right);
-        is_real := source.resulttype.def.deftype = floatdef;
-        
-        { get len/frac parameters }
-        lenpara := nil;
-        fracpara := nil;
-        if (cpf_is_colon_para in tcallparanode(dest.right).callparaflags) then
-          begin
-            lenpara := tcallparanode(dest.right);
-            if (cpf_is_colon_para in tcallparanode(lenpara.right).callparaflags) then
-              begin
-                fracpara := lenpara;
-                lenpara := tcallparanode(lenpara.right);
-              end;
-          end;
-
-        { generate the parameter list for the compilerproc }
-        newparas := dest;
-
-        { if we have a float parameter, insert the realtype, len and fracpara parameters }
-        if is_real then
-          begin
-            { insert realtype parameter }
-            newparas.right := ccallparanode.create(cordconstnode.create(
-              ord(tfloatdef(source.left.resulttype.def).typ),s32bittype),newparas.right);
-            { if necessary, insert a fraction parameter }
-            if not assigned(fracpara) then
-              begin
-                tcallparanode(newparas.right).right := ccallparanode.create(
-                  cordconstnode.create(-1,s32bittype),tcallparanode(newparas.right).right);
-                fracpara := tcallparanode(tcallparanode(newparas.right).right);
-              end;
-            { if necessary, insert a length para }
-            if not assigned(lenpara) then
-              fracpara.right := ccallparanode.create(cordconstnode.create(-32767,s32bittype),
-                fracpara.right);
-          end
-        else
-          { for a normal parameter, insert a only length parameter if one is missing }
-          if not assigned(lenpara) then
-            newparas.right := ccallparanode.create(cordconstnode.create(-1,s32bittype),
-              newparas.right);
-        
-        { remove the parameters from the original node so they won't get disposed, }
-        { since they're reused                                                     }
-        left := nil;
-        
-        { create procedure name }
-        procname := 'fpc_' + lowercase(tstringdef(dest.resulttype.def).stringtypname)+'_';
-        if is_real then
-          procname := procname + 'float'
-        else
-          case torddef(dest.resulttype.def).typ of
-            u32bit:
-              procname := procname + 'cardinal';
-            u64bit:
-              procname := procname + 'qword';
-            s64bit:
-              procname := procname + 'int64';
-            else
-              procname := procname + 'longint';
-          end;
-        
-        { create the call node, }
-        newnode := ccallnode.createintern(procname,newparas);
-        { firstpass it }
-        firstpass(newnode);
-        
-        { and return it }
-        result := newnode;
-      end;
-      
-      
-    function tinlinenode.reset_rewrite_typed_pass_1: tnode;
-      begin
-        { add the recsize parameter }
-        { note: for some reason, the parameter of intern procedures with only one }
-        {   parameter is gets lifted out of its original tcallparanode (see round }
-        {   line 1301 of ncal.pas), so recreate a tcallparanode here (JM)         }
-        left := ccallparanode.create(cordconstnode.create(
-          tfiledef(left.resulttype.def).typedfiletype.def.size,s32bittype),
-          ccallparanode.create(left,nil));
-        { create the correct call }
-        if inlinenumber=in_reset_typedfile then
-          result := ccallnode.createintern('fpc_reset_typed',left)
-        else
-          result := ccallnode.createintern('fpc_rewrite_typed',left);
-        firstpass(result);
-        { make sure left doesn't get disposed, since we use it in the new call }
-        left := nil;
-      end;
-{$endif hascompilerproc}
-
 
     function tinlinenode.pass_1 : tnode;
       var
@@ -1693,6 +2303,10 @@ implementation
           in_write_x,
           in_writeln_x :
             begin
+{$ifdef hascompilerproc}
+               { should be handled by det_resulttype }
+               internalerror(200108234);
+{$else hascompilerproc}
                { needs a call }
                procinfo^.flags:=procinfo^.flags or pi_do_call;
                { true, if readln needs an extra register }
@@ -1744,8 +2358,8 @@ implementation
                     if extra_register then
                       inc(registers32);
                  end;
+{$endif hascompilerproc}
             end;
-
          in_settextbuf_file_x :
            internalerror(200104262);
 
@@ -1755,7 +2369,8 @@ implementation
 {$ifndef hascompilerproc}
               procinfo^.flags:=procinfo^.flags or pi_do_call;
 {$else not hascompilerproc}
-              result := reset_rewrite_typed_pass_1;
+              { should already be removed in det_resulttype (JM) }
+              internalerror(200108236);
 {$endif not hascompilerproc}
            end;
 
@@ -1766,7 +2381,8 @@ implementation
               { calc registers }
               left_max;
 {$else not hascompilerproc}
-              result := str_pass_1;
+              { should already be removed in det_resulttype (JM) }
+              internalerror(200108235);
 {$endif not hascompilerproc}
            end;
 
@@ -1926,7 +2542,22 @@ begin
 end.
 {
   $Log$
-  Revision 1.48  2001-08-13 15:39:52  jonas
+  Revision 1.49  2001-08-23 14:28:35  jonas
+    + tempcreate/ref/delete nodes (allows the use of temps in the
+      resulttype and first pass)
+    * made handling of read(ln)/write(ln) processor independent
+    * moved processor independent handling for str and reset/rewrite-typed
+      from firstpass to resulttype pass
+    * changed names of helpers in text.inc to be generic for use as
+      compilerprocs + added "iocheck" directive for most of them
+    * reading of ordinals is done by procedures instead of functions
+      because otherwise FPC_IOCHECK overwrote the result before it could
+      be stored elsewhere (range checking still works)
+    * compilerprocs can now be used in the system unit before they are
+      implemented
+    * added note to errore.msg that booleans can't be read using read/readln
+
+  Revision 1.48  2001/08/13 15:39:52  jonas
     * made in_reset_typedfile/in_rewrite_typedfile handling processor
       independent
 

+ 20 - 1
compiler/node.pas

@@ -118,6 +118,8 @@ interface
           procinlinen,     {Procedures that can be inlined }
           arrayconstructorn, {Construction node for [...] parsing}
           arrayconstructorrangen, {Range element to allow sets in array construction tree}
+          tempn,     { for temps in the result/firstpass }
+          temprefn,  { references to temps }
           { added for optimizations where we cannot suppress }
           addoptn,
           nothingn,
@@ -203,6 +205,8 @@ interface
           'procinlinen',
           'arrayconstructn',
           'arrayconstructrangen',
+          'tempn',
+          'temprefn',
           'addoptn',
           'nothingn',
           'loadvmtn');
@@ -797,7 +801,22 @@ implementation
 end.
 {
   $Log$
-  Revision 1.18  2001-07-30 20:59:27  peter
+  Revision 1.19  2001-08-23 14:28:36  jonas
+    + tempcreate/ref/delete nodes (allows the use of temps in the
+      resulttype and first pass)
+    * made handling of read(ln)/write(ln) processor independent
+    * moved processor independent handling for str and reset/rewrite-typed
+      from firstpass to resulttype pass
+    * changed names of helpers in text.inc to be generic for use as
+      compilerprocs + added "iocheck" directive for most of them
+    * reading of ordinals is done by procedures instead of functions
+      because otherwise FPC_IOCHECK overwrote the result before it could
+      be stored elsewhere (range checking still works)
+    * compilerprocs can now be used in the system unit before they are
+      implemented
+    * added note to errore.msg that booleans can't be read using read/readln
+
+  Revision 1.18  2001/07/30 20:59:27  peter
     * m68k updates from v10 merged
 
   Revision 1.17  2001/06/04 18:14:16  peter

+ 26 - 3
compiler/pdecsub.pas

@@ -1116,6 +1116,11 @@ begin
     end;
 end;
 
+procedure pd_compilerproc;
+begin
+  aktprocsym.definition.setmangledname(lower(aktprocsym.name));
+end;
+
 
 type
    pd_handler=procedure;
@@ -1443,7 +1448,7 @@ const
     ),(
       idtok:_COMPILERPROC;
       pd_flags : pd_interface+pd_implemen+pd_body+pd_notobjintf;
-      handler  : nil;
+      handler  : {$ifdef FPCPROCVAR}@{$endif}pd_compilerproc;
       pocall   : [pocall_compilerproc];
       pooption : [];
       mutexclpocall : [];
@@ -1841,7 +1846,10 @@ const
                             { also update the realname that is stored in the ppu }
                             stringdispose(aktprocsym._realname);
                             aktprocsym._realname:=stringdup('$'+aktprocsym.name);
-                            aktprocsym.definition.setmangledname(aktprocsym.name);
+                            { the mangeled name is already changed by the pd_compilerproc }
+                            { handler. It must be done immediately because if we have a   }
+                            { call to a compilerproc before it's implementation is        }
+                            { encountered, it must already use the new mangled name (JM)  }
                           end;
                          check_identical_proc:=true;
                          break;
@@ -1918,7 +1926,22 @@ const
 end.
 {
   $Log$
-  Revision 1.34  2001-08-22 21:16:21  florian
+  Revision 1.35  2001-08-23 14:28:36  jonas
+    + tempcreate/ref/delete nodes (allows the use of temps in the
+      resulttype and first pass)
+    * made handling of read(ln)/write(ln) processor independent
+    * moved processor independent handling for str and reset/rewrite-typed
+      from firstpass to resulttype pass
+    * changed names of helpers in text.inc to be generic for use as
+      compilerprocs + added "iocheck" directive for most of them
+    * reading of ordinals is done by procedures instead of functions
+      because otherwise FPC_IOCHECK overwrote the result before it could
+      be stored elsewhere (range checking still works)
+    * compilerprocs can now be used in the system unit before they are
+      implemented
+    * added note to errore.msg that booleans can't be read using read/readln
+
+  Revision 1.34  2001/08/22 21:16:21  florian
     * some interfaces related problems regarding
       mapping of interface implementions fixed
 

+ 20 - 2
compiler/pstatmnt.pas

@@ -1085,7 +1085,10 @@ implementation
                       resulttypepass(tlabelnode(p).left);
                     end;
 
-                   if not(p.nodetype in [calln,assignn,breakn,inlinen,continuen,labeln]) then
+                   { blockn support because a read/write is changed into a blocknode }
+                   { with a separate statement for each read/write operation (JM)    }
+                   { the same is true for val() if the third parameter is not 32 bit }
+                   if not(p.nodetype in [calln,assignn,breakn,inlinen,continuen,labeln,blockn]) then
                      Message(cg_e_illegal_expression);
                    { specify that we don't use the value returned by the call }
                    { Question : can this be also improtant
@@ -1222,7 +1225,22 @@ implementation
 end.
 {
   $Log$
-  Revision 1.32  2001-08-06 21:40:47  peter
+  Revision 1.33  2001-08-23 14:28:36  jonas
+    + tempcreate/ref/delete nodes (allows the use of temps in the
+      resulttype and first pass)
+    * made handling of read(ln)/write(ln) processor independent
+    * moved processor independent handling for str and reset/rewrite-typed
+      from firstpass to resulttype pass
+    * changed names of helpers in text.inc to be generic for use as
+      compilerprocs + added "iocheck" directive for most of them
+    * reading of ordinals is done by procedures instead of functions
+      because otherwise FPC_IOCHECK overwrote the result before it could
+      be stored elsewhere (range checking still works)
+    * compilerprocs can now be used in the system unit before they are
+      implemented
+    * added note to errore.msg that booleans can't be read using read/readln
+
+  Revision 1.32  2001/08/06 21:40:47  peter
     * funcret moved from tprocinfo to tprocdef
 
   Revision 1.31  2001/06/03 21:57:37  peter

+ 49 - 1
rtl/inc/compproc.inc

@@ -104,6 +104,39 @@ procedure fpc_WideStr_Float(d : ValReal;len,fr,rt : longint;var s : WideString);
 Procedure fpc_WideStr_Cardinal(C : Cardinal;Len : Longint; Var S : WideString); compilerproc;
 Procedure fpc_WideStr_Longint(L : Longint; Len : Longint; Var S : WideString); compilerproc;
 
+{ from text.inc }
+Procedure fpc_Write_End(var f:Text); compilerproc;
+Procedure fpc_Writeln_End(var f:Text); compilerproc;
+Procedure fpc_Write_Text_ShortStr(Len : Longint;var f : Text;const s : String); compilerproc;
+Procedure fpc_Write_Text_Pchar_as_Array(Len : Longint;var f : Text;const s : array of char); compilerproc;
+Procedure fpc_Write_Text_PChar_As_Pointer(Len : Longint;var f : Text;p : PChar); compilerproc;
+Procedure fpc_Write_Text_AnsiStr (Len : Longint; Var f : Text; S : AnsiString); compilerproc;
+{$ifdef HASWIDESTRING}
+Procedure fpc_Write_Text_WideStr (Len : Longint; Var f : Text; S : WideString); compilerproc;
+{$endif HASWIDESTRING}
+Procedure fpc_Write_Text_SInt(Len : Longint;var t : Text;l : ValSInt); compilerproc;
+Procedure fpc_Write_Text_UInt(Len : Longint;var t : Text;l : ValUInt); compilerproc;
+procedure fpc_write_text_qword(len : longint;var t : text;q : qword); compilerproc;
+procedure fpc_write_text_int64(len : longint;var t : text;i : int64); compilerproc;
+Procedure fpc_Write_Text_Float(rt,fixkomma,Len : Longint;var t : Text;r : ValReal); compilerproc;
+Procedure fpc_Write_Text_Boolean(Len : Longint;var t : Text;b : Boolean); compilerproc;
+Procedure fpc_Write_Text_Char(Len : Longint;var t : Text;c : Char); compilerproc;
+{$ifdef HASWIDECHAR}
+Procedure fpc_Write_Text_WideChar(Len : Longint;var t : Text;c : WideChar); compilerproc;
+{$endif HASWIDECHAR}
+Procedure fpc_Read_End(var f:Text); compilerproc;
+Procedure fpc_ReadLn_End(var f : Text); compilerproc;
+Procedure fpc_Read_Text_ShortStr(var f : Text;var s : String); compilerproc;
+Procedure fpc_Read_Text_PChar_As_Pointer(var f : Text;var s : PChar); compilerproc;
+Procedure fpc_Read_Text_PChar_As_Array(var f : Text;var s : array of char); compilerproc;
+Procedure fpc_Read_Text_AnsiStr(var f : Text;var s : AnsiString); compilerproc;
+Procedure fpc_Read_Text_Char(var f : Text; var c : char); compilerproc;
+Procedure fpc_Read_Text_SInt(var f : Text; var l :ValSInt); compilerproc;
+Procedure fpc_Read_Text_UInt(var f : Text; var u :ValUInt); compilerproc;
+Procedure fpc_Read_Text_Float(var f : Text; var v :ValReal); compilerproc;
+Procedure fpc_Read_Text_QWord(var f : text; var q : qword); compilerproc;
+Procedure fpc_Read_Text_Int64(var f : text; var i : int64); compilerproc;
+
 { from int64.inc }
 procedure fpc_shortstr_qword(v : qword;len : longint;var s : shortstring); compilerproc;
 procedure fpc_shortstr_int64(v : int64;len : longint;var s : shortstring); compilerproc;
@@ -197,7 +230,22 @@ Procedure fpc_typed_read(TypeSize : Longint;var f : TypedFile;var Buf); compiler
 
 {
   $Log$
-  Revision 1.3  2001-08-13 12:40:16  jonas
+  Revision 1.4  2001-08-23 14:28:36  jonas
+    + tempcreate/ref/delete nodes (allows the use of temps in the
+      resulttype and first pass)
+    * made handling of read(ln)/write(ln) processor independent
+    * moved processor independent handling for str and reset/rewrite-typed
+      from firstpass to resulttype pass
+    * changed names of helpers in text.inc to be generic for use as
+      compilerprocs + added "iocheck" directive for most of them
+    * reading of ordinals is done by procedures instead of functions
+      because otherwise FPC_IOCHECK overwrote the result before it could
+      be stored elsewhere (range checking still works)
+    * compilerprocs can now be used in the system unit before they are
+      implemented
+    * added note to errore.msg that booleans can't be read using read/readln
+
+  Revision 1.3  2001/08/13 12:40:16  jonas
     * renamed some str(x,y) and val(x,y) helpers so the naming scheme is the
       same for all string types
     + added the str(x,y) and val(x,y,z) helpers for int64/qword to

+ 228 - 132
rtl/inc/text.inc

@@ -392,7 +392,7 @@ End;
                                Write(Ln)
 *****************************************************************************}
 
-Procedure WriteBuffer(var f:TextRec;const b;len:longint);
+Procedure WriteBuffer(var f:Text;const b;len:longint);
 var
   p   : pchar;
   left,
@@ -400,47 +400,47 @@ var
 begin
   p:=pchar(@b);
   idx:=0;
-  left:=f.BufSize-f.BufPos;
+  left:=TextRec(f).BufSize-TextRec(f).BufPos;
   while len>left do
    begin
-     move(p[idx],f.Bufptr^[f.BufPos],left);
+     move(p[idx],TextRec(f).Bufptr^[TextRec(f).BufPos],left);
      dec(len,left);
      inc(idx,left);
-     inc(f.BufPos,left);
-     FileFunc(f.InOutFunc)(f);
-     left:=f.BufSize-f.BufPos;
+     inc(TextRec(f).BufPos,left);
+     FileFunc(TextRec(f).InOutFunc)(TextRec(f));
+     left:=TextRec(f).BufSize-TextRec(f).BufPos;
    end;
-  move(p[idx],f.Bufptr^[f.BufPos],len);
-  inc(f.BufPos,len);
+  move(p[idx],TextRec(f).Bufptr^[TextRec(f).BufPos],len);
+  inc(TextRec(f).BufPos,len);
 end;
 
 
-Procedure WriteBlanks(var f:TextRec;len:longint);
+Procedure WriteBlanks(var f:Text;len:longint);
 var
   left : longint;
 begin
-  left:=f.BufSize-f.BufPos;
+  left:=TextRec(f).BufSize-TextRec(f).BufPos;
   while len>left do
    begin
-     FillChar(f.Bufptr^[f.BufPos],left,' ');
+     FillChar(TextRec(f).Bufptr^[TextRec(f).BufPos],left,' ');
      dec(len,left);
-     inc(f.BufPos,left);
-     FileFunc(f.InOutFunc)(f);
-     left:=f.BufSize-f.BufPos;
+     inc(TextRec(f).BufPos,left);
+     FileFunc(TextRec(f).InOutFunc)(TextRec(f));
+     left:=TextRec(f).BufSize-TextRec(f).BufPos;
    end;
-  FillChar(f.Bufptr^[f.BufPos],len,' ');
-  inc(f.BufPos,len);
+  FillChar(TextRec(f).Bufptr^[TextRec(f).BufPos],len,' ');
+  inc(TextRec(f).BufPos,len);
 end;
 
 
-Procedure Write_End(var f:TextRec);[Public,Alias:'FPC_WRITE_END'];
+Procedure fpc_Write_End(var f:Text);[Public,Alias:'FPC_WRITE_END']; iocheck; {$ifdef hascompilerproc} compilerproc; {$endif}
 begin
-  if f.FlushFunc<>nil then
-   FileFunc(f.FlushFunc)(f);
+  if TextRec(f).FlushFunc<>nil then
+   FileFunc(TextRec(f).FlushFunc)(TextRec(f));
 end;
 
 
-Procedure Writeln_End(var f:TextRec);[Public,Alias:'FPC_WRITELN_END'];
+Procedure fpc_Writeln_End(var f:Text);[Public,Alias:'FPC_WRITELN_END']; iocheck; {$ifdef hascompilerproc} compilerproc; {$endif}
 const
 {$IFDEF SHORT_LINEBREAK}
   eollen=1;
@@ -456,14 +456,14 @@ const
 {$ENDIF SHORT_LINEBREAK}
 begin
   If InOutRes <> 0 then exit;
-  case f.mode of
+  case TextRec(f).mode of
     fmOutput { fmAppend gets changed to fmOutPut in do_open (JM) }:
       begin
         { Write EOL }
         WriteBuffer(f,(@sLineBreak+1)^,length(sLineBreak));
         { Flush }
-        if f.FlushFunc<>nil then
-          FileFunc(f.FlushFunc)(f);
+        if TextRec(f).FlushFunc<>nil then
+          FileFunc(TextRec(f).FlushFunc)(TextRec(f));
       end;
     fmInput: InOutRes:=105
     else InOutRes:=103;
@@ -471,11 +471,11 @@ begin
 end;
 
 
-Procedure Write_Str(Len : Longint;var f : TextRec;const s : String);[Public,Alias:'FPC_WRITE_TEXT_SHORTSTR'];
+Procedure fpc_Write_Text_ShortStr(Len : Longint;var f : Text;const s : String); iocheck; [Public,Alias:'FPC_WRITE_TEXT_SHORTSTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
 Begin
   If (InOutRes<>0) then
    exit;
-  case f.mode of
+  case TextRec(f).mode of
     fmOutput { fmAppend gets changed to fmOutPut in do_open (JM) }:
       begin
         If Len>Length(s) Then
@@ -487,15 +487,18 @@ Begin
   end;
 End;
 
+{ provide local access to write_str }
+procedure Write_Str(Len : Longint;var f : Text;const s : String); iocheck; [external name 'FPC_WRITE_TEXT_SHORTSTR'];
 
-Procedure Write_Array(Len : Longint;var f : TextRec;const s : array of char);[Public,Alias:'FPC_WRITE_TEXT_PCHAR_AS_ARRAY'];
+
+Procedure fpc_Write_Text_Pchar_as_Array(Len : Longint;var f : Text;const s : array of char); iocheck; [Public,Alias:'FPC_WRITE_TEXT_PCHAR_AS_ARRAY']; {$ifdef hascompilerproc} compilerproc; {$endif}
 var
   ArrayLen : longint;
   p : pchar;
 Begin
   If (InOutRes<>0) then
    exit;
-  case f.mode of
+  case TextRec(f).mode of
     fmOutput { fmAppend gets changed to fmOutPut in do_open (JM) }:
       begin
         p:=pchar(@s);
@@ -515,13 +518,13 @@ Begin
 End;
 
 
-Procedure Write_PChar(Len : Longint;var f : TextRec;p : PChar);[Public,Alias:'FPC_WRITE_TEXT_PCHAR_AS_POINTER'];
+Procedure fpc_Write_Text_PChar_As_Pointer(Len : Longint;var f : Text;p : PChar); iocheck; [Public,Alias:'FPC_WRITE_TEXT_PCHAR_AS_POINTER']; {$ifdef hascompilerproc} compilerproc; {$endif}
 var
   PCharLen : longint;
 Begin
   If (p=nil) or (InOutRes<>0) then
    exit;
-  case f.mode of
+  case TextRec(f).mode of
     fmOutput { fmAppend gets changed to fmOutPut in do_open (JM) }:
       begin
         PCharLen:=StrLen(p);
@@ -535,7 +538,7 @@ Begin
 End;
 
 
-Procedure Write_Text_AnsiString (Len : Longint; Var f : TextRec; S : AnsiString);[Public,alias:'FPC_WRITE_TEXT_ANSISTR'];
+Procedure fpc_Write_Text_AnsiStr (Len : Longint; Var f : Text; S : AnsiString); iocheck; [Public,alias:'FPC_WRITE_TEXT_ANSISTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
 {
  Writes a AnsiString to the Text file T
 }
@@ -544,7 +547,7 @@ var
 begin
   If (pointer(S)=nil) or (InOutRes<>0) then
    exit;
-  case f.mode of
+  case TextRec(f).mode of
     fmOutput { fmAppend gets changed to fmOutPut in do_open (JM) }:
       begin
         SLen:=Length(s);
@@ -559,7 +562,7 @@ end;
 
 
 {$ifdef HASWIDESTRING}
-Procedure Write_Text_WideString (Len : Longint; Var f : TextRec; S : WideString);[Public,alias:'FPC_WRITE_TEXT_WIDESTR'];
+Procedure fpc_Write_Text_WideStr (Len : Longint; Var f : Text; S : WideString); iocheck; [Public,alias:'FPC_WRITE_TEXT_WIDESTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
 {
  Writes a WideString to the Text file T
 }
@@ -568,7 +571,7 @@ var
 begin
   If (pointer(S)=nil) or (InOutRes<>0) then
    exit;
-  case f.mode of
+  case TextRec(f).mode of
     fmOutput { fmAppend gets changed to fmOutPut in do_open (JM) }:
       begin
         SLen:=Length(s);
@@ -582,7 +585,7 @@ begin
 end;
 {$endif HASWIDESTRING}
 
-Procedure Write_SInt(Len : Longint;var t : TextRec;l : ValSInt);[Public,Alias:'FPC_WRITE_TEXT_SINT'];
+Procedure fpc_Write_Text_SInt(Len : Longint;var t : Text;l : ValSInt); iocheck; [Public,Alias:'FPC_WRITE_TEXT_SINT']; {$ifdef hascompilerproc} compilerproc; {$endif}
 var
   s : String;
 Begin
@@ -593,7 +596,7 @@ Begin
 End;
 
 
-Procedure Write_UInt(Len : Longint;var t : TextRec;l : ValUInt);[Public,Alias:'FPC_WRITE_TEXT_UINT'];
+Procedure fpc_Write_Text_UInt(Len : Longint;var t : Text;l : ValUInt); iocheck; [Public,Alias:'FPC_WRITE_TEXT_UINT']; {$ifdef hascompilerproc} compilerproc; {$endif}
 var
   s : String;
 Begin
@@ -604,7 +607,7 @@ Begin
 End;
 
 
-procedure write_qword(len : longint;var t : textrec;q : qword);[public,alias:'FPC_WRITE_TEXT_QWORD'];
+procedure fpc_write_text_qword(len : longint;var t : text;q : qword); iocheck; [public,alias:'FPC_WRITE_TEXT_QWORD']; {$ifdef hascompilerproc} compilerproc; {$endif}
 var
   s : string;
 begin
@@ -614,7 +617,7 @@ begin
   write_str(len,t,s);
 end;
 
-procedure write_int64(len : longint;var t : textrec;i : int64);[public,alias:'FPC_WRITE_TEXT_INT64'];
+procedure fpc_write_text_int64(len : longint;var t : text;i : int64); iocheck; [public,alias:'FPC_WRITE_TEXT_INT64']; {$ifdef hascompilerproc} compilerproc; {$endif}
 var
   s : string;
 begin
@@ -625,7 +628,7 @@ begin
 end;
 
 
-Procedure Write_Float(rt,fixkomma,Len : Longint;var t : TextRec;r : ValReal);[Public,Alias:'FPC_WRITE_TEXT_FLOAT'];
+Procedure fpc_Write_Text_Float(rt,fixkomma,Len : Longint;var t : Text;r : ValReal); iocheck; [Public,Alias:'FPC_WRITE_TEXT_FLOAT']; {$ifdef hascompilerproc} compilerproc; {$endif}
 var
   s : String;
 Begin
@@ -636,7 +639,7 @@ Begin
 End;
 
 
-Procedure Write_Boolean(Len : Longint;var t : TextRec;b : Boolean);[Public,Alias:'FPC_WRITE_TEXT_BOOLEAN'];
+Procedure fpc_Write_Text_Boolean(Len : Longint;var t : Text;b : Boolean); iocheck; [Public,Alias:'FPC_WRITE_TEXT_BOOLEAN']; {$ifdef hascompilerproc} compilerproc; {$endif}
 Begin
   If (InOutRes<>0) then
    exit;
@@ -648,7 +651,7 @@ Begin
 End;
 
 
-Procedure Write_Char(Len : Longint;var t : TextRec;c : Char);[Public,Alias:'FPC_WRITE_TEXT_CHAR'];
+Procedure fpc_Write_Text_Char(Len : Longint;var t : Text;c : Char); iocheck; [Public,Alias:'FPC_WRITE_TEXT_CHAR']; {$ifdef hascompilerproc} compilerproc; {$endif}
 Begin
   If (InOutRes<>0) then
    exit;
@@ -662,15 +665,15 @@ Begin
    end;
   If Len>1 Then
    WriteBlanks(t,Len-1);
-  If t.BufPos+1>=t.BufSize Then
-   FileFunc(t.InOutFunc)(t);
-  t.Bufptr^[t.BufPos]:=c;
-  Inc(t.BufPos);
+  If TextRec(t).BufPos+1>=TextRec(t).BufSize Then
+   FileFunc(TextRec(t).InOutFunc)(TextRec(t));
+  TextRec(t).Bufptr^[TextRec(t).BufPos]:=c;
+  Inc(TextRec(t).BufPos);
 End;
 
 
 {$ifdef HASWIDECHAR}
-Procedure Write_WideChar(Len : Longint;var t : TextRec;c : WideChar);[Public,Alias:'FPC_WRITE_TEXT_WIDECHAR'];
+Procedure fpc_Write_Text_WideChar(Len : Longint;var t : Text;c : WideChar); iocheck; [Public,Alias:'FPC_WRITE_TEXT_WIDECHAR']; {$ifdef hascompilerproc} compilerproc; {$endif}
 var
   ch : char;
 Begin
@@ -686,11 +689,11 @@ Begin
    end;
   If Len>1 Then
    WriteBlanks(t,Len-1);
-  If t.BufPos+1>=t.BufSize Then
-   FileFunc(t.InOutFunc)(t);
+  If TextRec(t).BufPos+1>=TextRec(t).BufSize Then
+   FileFunc(TextRec(t).InOutFunc)(TextRec(t));
   ch:=c;
-  t.Bufptr^[t.BufPos]:=ch;
-  Inc(t.BufPos);
+  TextRec(t).Bufptr^[TextRec(t).BufPos]:=ch;
+  Inc(TextRec(t).BufPos);
 End;
 {$endif HASWIDECHAR}
 
@@ -699,18 +702,18 @@ End;
                                 Read(Ln)
 *****************************************************************************}
 
-Function NextChar(var f:TextRec;var s:string):Boolean;
+Function NextChar(var f:Text;var s:string):Boolean;
 begin
-  if f.BufPos<f.BufEnd then
+  if TextRec(f).BufPos<TextRec(f).BufEnd then
    begin
      if length(s)<high(s) then
       begin
         inc(s[0]);
-        s[length(s)]:=f.BufPtr^[f.BufPos];
+        s[length(s)]:=TextRec(f).BufPtr^[TextRec(f).BufPos];
       end;
-     Inc(f.BufPos);
-     If f.BufPos>=f.BufEnd Then
-      FileFunc(f.InOutFunc)(f);
+     Inc(TextRec(f).BufPos);
+     If TextRec(f).BufPos>=TextRec(f).BufEnd Then
+      FileFunc(TextRec(f).InOutFunc)(TextRec(f));
      NextChar:=true;
    end
   else
@@ -718,7 +721,7 @@ begin
 end;
 
 
-Function IgnoreSpaces(var f:TextRec):Boolean;
+Function IgnoreSpaces(var f:Text):Boolean;
 {
   Removes all leading spaces,tab,eols from the input buffer, returns true if
   the buffer is empty
@@ -728,14 +731,14 @@ var
 begin
   s:='';
   IgnoreSpaces:=false;
-  while f.Bufptr^[f.BufPos] in [#9,#10,#13,' '] do
+  while TextRec(f).Bufptr^[TextRec(f).BufPos] in [#9,#10,#13,' '] do
    if not NextChar(f,s) then
     exit;
   IgnoreSpaces:=true;
 end;
 
 
-procedure ReadNumeric(var f:TextRec;var s:string);
+procedure ReadNumeric(var f:Text;var s:string);
 {
   Read numeric input, if buffer is empty then return True
 }
@@ -743,24 +746,24 @@ begin
   repeat
     if not NextChar(f,s) then
       exit;
-  until (length(s)=high(s)) or (f.BufPtr^[f.BufPos] in [#9,#10,#13,' ']);
+  until (length(s)=high(s)) or (TextRec(f).BufPtr^[TextRec(f).BufPos] in [#9,#10,#13,' ']);
 end;
 
 
-Procedure Read_End(var f:TextRec);[Public,Alias:'FPC_READ_END'];
+Procedure fpc_Read_End(var f:Text);[Public,Alias:'FPC_READ_END']; iocheck; {$ifdef hascompilerproc} compilerproc; {$endif}
 begin
-  if f.FlushFunc<>nil then
-   FileFunc(f.FlushFunc)(f);
+  if TextRec(f).FlushFunc<>nil then
+   FileFunc(TextRec(f).FlushFunc)(TextRec(f));
 end;
 
 
-Procedure ReadLn_End(var f : TextRec);[Public,Alias:'FPC_READLN_END'];
+Procedure fpc_ReadLn_End(var f : Text);[Public,Alias:'FPC_READLN_END']; iocheck; {$ifdef hascompilerproc} compilerproc; {$endif}
 var prev: char;
 Begin
 { Check error and if file is open and load buf if empty }
   If (InOutRes<>0) then
    exit;
-  if (f.mode<>fmInput) Then
+  if (TextRec(f).mode<>fmInput) Then
    begin
      case TextRec(f).mode of
       fmOutPut,fmAppend:
@@ -770,48 +773,48 @@ Begin
      end;
      exit;
    end;
-  if f.BufPos>=f.BufEnd Then
+  if TextRec(f).BufPos>=TextRec(f).BufEnd Then
    begin
-     FileFunc(f.InOutFunc)(f);
-     if (f.BufPos>=f.BufEnd) then
+     FileFunc(TextRec(f).InOutFunc)(TextRec(f));
+     if (TextRec(f).BufPos>=TextRec(f).BufEnd) then
        { Flush if set }
        begin
-         if (f.FlushFunc<>nil) then
-           FileFunc(f.FlushFunc)(f);
+         if (TextRec(f).FlushFunc<>nil) then
+           FileFunc(TextRec(f).FlushFunc)(TextRec(f));
          exit;
        end;
    end;
   repeat
-    prev := f.BufPtr^[f.BufPos];
-    inc(f.BufPos);
+    prev := TextRec(f).BufPtr^[TextRec(f).BufPos];
+    inc(TextRec(f).BufPos);
 { no system uses #10#13 as line seperator (#10 = *nix, #13 = Mac, }
 { #13#10 = Dos), so if we've got #10, we can safely exit          }
     if prev = #10 then
       exit;
-    if f.BufPos>=f.BufEnd Then
+    if TextRec(f).BufPos>=TextRec(f).BufEnd Then
       begin
-        FileFunc(f.InOutFunc)(f);
-        if (f.BufPos>=f.BufEnd) then
+        FileFunc(TextRec(f).InOutFunc)(TextRec(f));
+        if (TextRec(f).BufPos>=TextRec(f).BufEnd) then
           { Flush if set }
           begin
-           if (f.FlushFunc<>nil) then
-             FileFunc(f.FlushFunc)(f);
+           if (TextRec(f).FlushFunc<>nil) then
+             FileFunc(TextRec(f).FlushFunc)(TextRec(f));
            exit;
          end;
       end;
    if (prev=#13) then
      { is there also a #10 after it? }
      begin
-       if (f.BufPtr^[f.BufPos]=#10) then
+       if (TextRec(f).BufPtr^[TextRec(f).BufPos]=#10) then
          { yes, skip that one as well }
-         inc(f.BufPos);
+         inc(TextRec(f).BufPos);
        exit;
      end;
   until false;
 End;
 
 
-Function ReadPCharLen(var f:TextRec;s:pchar;maxlen:longint):longint;
+Function ReadPCharLen(var f:Text;s:pchar;maxlen:longint):longint;
 var
   sPos,len : Longint;
   p,startp,maxp : pchar;
@@ -820,7 +823,7 @@ Begin
 { Check error and if file is open }
   If (InOutRes<>0) then
    exit;
-  if (f.mode<>fmInput) Then
+  if (TextRec(f).mode<>fmInput) Then
    begin
      case TextRec(f).mode of
        fmOutPut,fmAppend:
@@ -833,24 +836,24 @@ Begin
 { Read maximal until Maxlen is reached }
   sPos:=0;
   repeat
-    If f.BufPos>=f.BufEnd Then
+    If TextRec(f).BufPos>=TextRec(f).BufEnd Then
      begin
-       FileFunc(f.InOutFunc)(f);
-       If f.BufPos>=f.BufEnd Then
+       FileFunc(TextRec(f).InOutFunc)(TextRec(f));
+       If TextRec(f).BufPos>=TextRec(f).BufEnd Then
          break;
      end;
-    p:[email protected]^[f.BufPos];
-    if SPos+f.BufEnd-f.BufPos>MaxLen then
-     maxp:[email protected]^[f.BufPos+MaxLen-SPos]
+    p:=@TextRec(f).Bufptr^[TextRec(f).BufPos];
+    if SPos+TextRec(f).BufEnd-TextRec(f).BufPos>MaxLen then
+     maxp:=@TextRec(f).BufPtr^[TextRec(f).BufPos+MaxLen-SPos]
     else
-     maxp:[email protected]^[f.BufEnd];
+     maxp:=@TextRec(f).Bufptr^[TextRec(f).BufEnd];
     startp:=p;
   { search linefeed }
     while (p<maxp) and not(P^ in [#10,#13]) do
      inc(p);
   { calculate read bytes }
     len:=p-startp;
-    inc(f.BufPos,Len);
+    inc(TextRec(f).BufPos,Len);
     Move(startp^,s[sPos],Len);
     inc(sPos,Len);
   { was it a LF or CR? then leave }
@@ -862,19 +865,19 @@ Begin
 End;
 
 
-Procedure Read_String(var f : TextRec;var s : String);[Public,Alias:'FPC_READ_TEXT_SHORTSTR'];
+Procedure fpc_Read_Text_ShortStr(var f : Text;var s : String); iocheck; [Public,Alias:'FPC_READ_TEXT_SHORTSTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
 Begin
   s[0]:=chr(ReadPCharLen(f,pchar(@s[1]),high(s)));
 End;
 
 
-Procedure Read_PChar(var f : TextRec;var s : PChar);[Public,Alias:'FPC_READ_TEXT_PCHAR_AS_POINTER'];
+Procedure fpc_Read_Text_PChar_As_Pointer(var f : Text;var s : PChar); iocheck; [Public,Alias:'FPC_READ_TEXT_PCHAR_AS_POINTER']; {$ifdef hascompilerproc} compilerproc; {$endif}
 Begin
   pchar(s+ReadPCharLen(f,s,$7fffffff))^:=#0;
 End;
 
 
-Procedure Read_Array(var f : TextRec;var s : array of char);[Public,Alias:'FPC_READ_TEXT_PCHAR_AS_ARRAY'];
+Procedure fpc_Read_Text_PChar_As_Array(var f : Text;var s : array of char); iocheck; [Public,Alias:'FPC_READ_TEXT_PCHAR_AS_ARRAY']; {$ifdef hascompilerproc} compilerproc; {$endif}
 var
   len: longint;
 Begin
@@ -884,7 +887,7 @@ Begin
 End;
 
 
-Procedure Read_AnsiString(var f : TextRec;var s : AnsiString);[Public,Alias:'FPC_READ_TEXT_ANSISTR'];
+Procedure fpc_Read_Text_AnsiStr(var f : Text;var s : AnsiString); iocheck; [Public,Alias:'FPC_READ_TEXT_ANSISTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
 var
   slen,len : longint;
 Begin
@@ -899,14 +902,21 @@ Begin
   SetLength(S,Slen);
 End;
 
-
-Function Read_Char(var f : TextRec):char;[Public,Alias:'FPC_READ_TEXT_CHAR'];
+{$ifdef hascompilerproc}
+procedure fpc_Read_Text_Char(var f : Text; var c: char); iocheck; [Public,Alias:'FPC_READ_TEXT_CHAR'];compilerproc;
+{$else hascompilerproc}
+Function fpc_Read_Text_Char(var f : Text):char;[Public,Alias:'FPC_READ_TEXT_CHAR'];
+{$endif hascompilerproc}
 Begin
-  Read_Char:=#0;
+{$ifdef hascompilerproc}
+  c:=#0;
+{$else hascompilerproc}
+  fpc_Read_Text_Char:=#0;
+{$endif hascompilerproc}
 { Check error and if file is open }
   If (InOutRes<>0) then
    exit;
-  if (f.mode<>fmInput) Then
+  if (TextRec(f).mode<>fmInput) Then
    begin
      case TextRec(f).mode of
        fmOutPut,fmAppend:
@@ -917,27 +927,46 @@ Begin
      exit;
    end;
 { Read next char or EOF }
-  If f.BufPos>=f.BufEnd Then
+  If TextRec(f).BufPos>=TextRec(f).BufEnd Then
    begin
-     FileFunc(f.InOutFunc)(f);
-     If f.BufPos>=f.BufEnd Then
+     FileFunc(TextRec(f).InOutFunc)(TextRec(f));
+     If TextRec(f).BufPos>=TextRec(f).BufEnd Then
+{$ifdef hascompilerproc}
+       begin
+         c := #26;
+         exit;
+       end;
+{$else hascompilerproc}
        exit(#26);
+{$endif hascompilerproc}
    end;
-  Read_Char:=f.Bufptr^[f.BufPos];
-  inc(f.BufPos);
+{$ifdef hascompilerproc}
+  c:=TextRec(f).Bufptr^[TextRec(f).BufPos];
+{$else hascompilerproc}
+  fpc_Read_Text_Char:=TextRec(f).Bufptr^[TextRec(f).BufPos];
+{$endif hascompilerproc}
+  inc(TextRec(f).BufPos);
 end;
 
 
-Function Read_SInt(var f : TextRec):ValSInt;[Public,Alias:'FPC_READ_TEXT_SINT'];
+{$ifdef hascompilerproc}
+Procedure fpc_Read_Text_SInt(var f : Text; var l : ValSInt); iocheck; [Public,Alias:'FPC_READ_TEXT_SINT']; compilerproc;
+{$else hascompilerproc}
+Function fpc_Read_Text_SInt(var f : Text):ValSInt;[Public,Alias:'FPC_READ_TEXT_SINT'];
+{$endif hascompilerproc}
 var
   hs   : String;
   code : Longint;
 Begin
-  Read_SInt:=0;
+{$ifdef hascompilerproc}
+  l:=0;
+{$else hascompilerproc}
+  fpc_Read_Text_SInt:=0;
+{$endif hascompilerproc}
 { Leave if error or not open file, else check for empty buf }
   If (InOutRes<>0) then
    exit;
-  if (f.mode<>fmInput) Then
+  if (TextRec(f).mode<>fmInput) Then
    begin
      case TextRec(f).mode of
        fmOutPut,fmAppend:
@@ -947,27 +976,39 @@ Begin
      end;
      exit;
    end;
-  If f.BufPos>=f.BufEnd Then
-   FileFunc(f.InOutFunc)(f);
+  If TextRec(f).BufPos>=TextRec(f).BufEnd Then
+   FileFunc(TextRec(f).InOutFunc)(TextRec(f));
   hs:='';
   if IgnoreSpaces(f) then
    ReadNumeric(f,hs);
-  Val(hs,Read_SInt,code);
+{$ifdef hascompilerproc}
+  Val(hs,l,code);
+{$else hascompilerproc}
+  Val(hs,fpc_Read_Text_SInt,code);
+{$endif hascompilerproc}
   If code<>0 Then
    InOutRes:=106;
 End;
 
 
-Function Read_UInt(var f : TextRec):ValUInt;[Public,Alias:'FPC_READ_TEXT_UINT'];
+{$ifdef hascompilerproc}
+Procedure fpc_Read_Text_UInt(var f : Text; var u : ValUInt);  iocheck; [Public,Alias:'FPC_READ_TEXT_UINT']; compilerproc;
+{$else hascompilerproc}
+Function fpc_Read_Text_UInt(var f : Text):ValUInt;[Public,Alias:'FPC_READ_TEXT_UINT'];
+{$endif hascompilerproc}
 var
   hs   : String;
   code : longint;
 Begin
-  Read_UInt:=0;
+{$ifdef hascompilerproc}
+  u:=0;
+{$else hascompilerproc}
+  fpc_Read_Text_UInt:=0;
+{$endif hascompilerproc}
 { Leave if error or not open file, else check for empty buf }
   If (InOutRes<>0) then
    exit;
-  if (f.mode<>fmInput) Then
+  if (TextRec(f).mode<>fmInput) Then
    begin
      case TextRec(f).mode of
        fmOutPut,fmAppend:
@@ -977,27 +1018,39 @@ Begin
      end;
      exit;
    end;
-  If f.BufPos>=f.BufEnd Then
-   FileFunc(f.InOutFunc)(f);
+  If TextRec(f).BufPos>=TextRec(f).BufEnd Then
+   FileFunc(TextRec(f).InOutFunc)(TextRec(f));
   hs:='';
   if IgnoreSpaces(f) then
    ReadNumeric(f,hs);
-  val(hs,Read_UInt,code);
+{$ifdef hascompilerproc}
+  val(hs,u,code);
+{$else hascompilerproc}
+  val(hs,fpc_Read_Text_UInt,code);
+{$endif hascompilerproc}
   If code<>0 Then
    InOutRes:=106;
 End;
 
 
-Function Read_Float(var f : TextRec):ValReal;[Public,Alias:'FPC_READ_TEXT_FLOAT'];
+{$ifdef hascompilerproc}
+procedure fpc_Read_Text_Float(var f : Text; var v : ValReal); iocheck; [Public,Alias:'FPC_READ_TEXT_FLOAT']; compilerproc;
+{$else hascompilerproc}
+Function fpc_Read_Text_Float(var f : Text):ValReal;[Public,Alias:'FPC_READ_TEXT_FLOAT'];
+{$endif hascompilerproc}
 var
   hs : string;
   code : Word;
 begin
-  Read_Float:=0.0;
+{$ifdef hascompilerproc}
+  v:=0.0;
+{$else hascompilerproc}
+  fpc_Read_Text_Float:=0.0;
+{$endif hascompilerproc}
 { Leave if error or not open file, else check for empty buf }
   If (InOutRes<>0) then
    exit;
-  if (f.mode<>fmInput) Then
+  if (TextRec(f).mode<>fmInput) Then
    begin
      case TextRec(f).mode of
        fmOutPut,fmAppend:
@@ -1007,27 +1060,39 @@ begin
      end;
      exit;
    end;
-  If f.BufPos>=f.BufEnd Then
-   FileFunc(f.InOutFunc)(f);
+  If TextRec(f).BufPos>=TextRec(f).BufEnd Then
+   FileFunc(TextRec(f).InOutFunc)(TextRec(f));
   hs:='';
   if IgnoreSpaces(f) then
     ReadNumeric(f,hs);
-  val(hs,Read_Float,code);
+{$ifdef hascompilerproc}
+  val(hs,v,code);
+{$else hascompilerproc}
+  val(hs,fpc_Read_Text_Float,code);
+{$endif hascompilerproc}
   If code<>0 Then
    InOutRes:=106;
 end;
 
 
-function Read_QWord(var f : textrec) : qword;[public,alias:'FPC_READ_TEXT_QWORD'];
+{$ifdef hascompilerproc}
+procedure fpc_Read_Text_QWord(var f : text; var q : qword); iocheck; [public,alias:'FPC_READ_TEXT_QWORD']; compilerproc;
+{$else hascompilerproc}
+function fpc_Read_Text_QWord(var f : text) : qword;[public,alias:'FPC_READ_TEXT_QWORD'];
+{$endif hascompilerproc}
 var
   hs   : String;
   code : longint;
 Begin
-  Read_QWord:=0;
+{$ifdef hascompilerproc}
+  q:=0;
+{$else hascompilerproc}
+  fpc_Read_Text_QWord:=0;
+{$endif hascompilerproc}
   { Leave if error or not open file, else check for empty buf }
   If (InOutRes<>0) then
    exit;
-  if (f.mode<>fmInput) Then
+  if (TextRec(f).mode<>fmInput) Then
    begin
      case TextRec(f).mode of
        fmOutPut,fmAppend:
@@ -1037,26 +1102,38 @@ Begin
      end;
      exit;
    end;
-  If f.BufPos>=f.BufEnd Then
-   FileFunc(f.InOutFunc)(f);
+  If TextRec(f).BufPos>=TextRec(f).BufEnd Then
+   FileFunc(TextRec(f).InOutFunc)(TextRec(f));
   hs:='';
   if IgnoreSpaces(f) then
    ReadNumeric(f,hs);
-  val(hs,Read_QWord,code);
+{$ifdef hascompilerproc}
+  val(hs,q,code);
+{$else hascompilerproc}
+  val(hs,fpc_Read_Text_QWord,code);
+{$endif hascompilerproc}
   If code<>0 Then
    InOutRes:=106;
 End;
 
-function Read_Int64(var f : textrec) : int64;[public,alias:'FPC_READ_TEXT_INT64'];
+{$ifdef hascompilerproc}
+procedure fpc_Read_Text_Int64(var f : text; var i : int64); iocheck; [public,alias:'FPC_READ_TEXT_INT64']; compilerproc;
+{$else hascompilerproc}
+function fpc_Read_Text_Int64(var f : text) : int64;[public,alias:'FPC_READ_TEXT_INT64']; {$ifdef hascompilerproc} compilerproc; {$endif}
+{$endif hascompilerproc}
 var
   hs   : String;
   code : Longint;
 Begin
-  Read_Int64:=0;
+{$ifdef hascompilerproc}
+  i:=0;
+{$else hascompilerproc}
+  fpc_Read_Text_Int64:=0;
+{$endif hascompilerproc}
 { Leave if error or not open file, else check for empty buf }
   If (InOutRes<>0) then
    exit;
-  if (f.mode<>fmInput) Then
+  if (TextRec(f).mode<>fmInput) Then
    begin
      case TextRec(f).mode of
        fmOutPut,fmAppend:
@@ -1066,12 +1143,16 @@ Begin
      end;
      exit;
    end;
-  If f.BufPos>=f.BufEnd Then
-   FileFunc(f.InOutFunc)(f);
+  If TextRec(f).BufPos>=TextRec(f).BufEnd Then
+   FileFunc(TextRec(f).InOutFunc)(TextRec(f));
   hs:='';
   if IgnoreSpaces(f) then
    ReadNumeric(f,hs);
-  Val(hs,Read_Int64,code);
+{$ifdef hascompilerproc}
+  Val(hs,i,code);
+{$else hascompilerproc}
+  Val(hs,fpc_Read_Text_Int64,code);
+{$endif hascompilerproc}
   If code<>0 Then
    InOutRes:=106;
 End;
@@ -1103,7 +1184,22 @@ end;
 
 {
   $Log$
-  Revision 1.13  2001-08-22 20:49:18  peter
+  Revision 1.14  2001-08-23 14:28:36  jonas
+    + tempcreate/ref/delete nodes (allows the use of temps in the
+      resulttype and first pass)
+    * made handling of read(ln)/write(ln) processor independent
+    * moved processor independent handling for str and reset/rewrite-typed
+      from firstpass to resulttype pass
+    * changed names of helpers in text.inc to be generic for use as
+      compilerprocs + added "iocheck" directive for most of them
+    * reading of ordinals is done by procedures instead of functions
+      because otherwise FPC_IOCHECK overwrote the result before it could
+      be stored elsewhere (range checking still works)
+    * compilerprocs can now be used in the system unit before they are
+      implemented
+    * added note to errore.msg that booleans can't be read using read/readln
+
+  Revision 1.13  2001/08/22 20:49:18  peter
     * regenerated
 
   Revision 1.12  2001/08/19 11:23:10  peter