modula-2 home

  Home  
  Tutorial  
  Win32 API  
  Reference  
  Projects  
 

 

User Device for ISO Std Channel I/O to Memory

By Tom Breeden (tmb@virginia.edu)

 

I wanted to try implementing a new "device" to be useable integrated into the ISO standard channel I/O system. This enables output (and input) to your device to use the various procedures in ISO standard modules like TextIO, WholeIO, IOResult, IOChan, etc. Or, even more useful, to use higher level formatting and output routines of your own that make use of the ISO standard IO modules.

Ideally, I would have been able to consult The M2 ISO Standard I/O Architecture Manual, but actually ended up consulting the sources for modules like SeqFile, as implemented by R. Sutcliffe and G. Tischer, and modified by Stony Brook Software for their Windows distribution.

Another problem was that I did not really have my own different device. However, I did have a module for manipulating large amounts of text in memory, TextBlocks, and this could serve as the source and target of the channel IO.

So, here it is, module TBChans, along with TextBlocks, and a simple demo program TBChansDemo. I have used it on both Stony Brook Modula-2 and on a semi-ISO (unreleased) M2 compiler for Amiga (M68040).

The files in the download TBChans.zip include the complete sources of TBChans and TextBlocks, plus some dynamic string handling and other modules they depend upon.

Your comments are appreciated.


(*#########################*)
 DEFINITION MODULE TBChans;                      (* v0.1-031802 *)
(*#########################*)

                                     (* by Thomas Breeden, tmb@virginia.edu *)
(*
     "Device" for ISO Std Channel I/O to memory.

     This is an initial try at implementing a new ISO channel to use with
     TextIO, WholeIO, etc.

     The implementation is layered on a module, TextBlocks, and the GetTB()
     provides a hook to get the underlying text data.
*)

(*
Copyright (C) 1997-2003 Thomas Breeden.

Permission to use, copy, modify and distribute this software and its
documentation for any purpose and without fee is hereby granted, provided that
the above copyright notice appear in all copies and that both the copyright
notice and this permission notice appear in supporting documentation.
Thomas Breeden makes no representations about the suitability of this software
for any purpose. It is provided "as is" without express or implied warranty.
*)

IMPORT IOChan, ChanConsts;
FROM TextBlocks IMPORT TextBlock;

TYPE ChanId         = IOChan.ChanId;
     OpenResults    = ChanConsts.OpenResults;

PROCEDURE OpenTB(VAR cid:ChanId; VAR res:OpenResults);

PROCEDURE Reread(cid:ChanId);
PROCEDURE Rewrite(cid:ChanId);

PROCEDURE Close(VAR cid:ChanId);

PROCEDURE IsTBFile(cid:ChanId):BOOLEAN;

PROCEDURE GetTB(cid:ChanId):TextBlock;

(* NOTE  1. Writes always go at the end, unless Rewrite() was just called.
         2. Currently, only text r/w, no rawIO.
         3. OpenTB() always creates an empty TextBlock. It is ok to get that
            with GetTB() and fill it up externally before doing any reads with
            channel IO procs.
         4. CloseTB() deallocates the TextBlock.

VERSION HISTORY

vx.x-090397
v0.1-031802    -Changed OpenTBWrite() to just OpenTB(). For now, all TBChans
                are Read/Write. Rewrite clears it.
*)

END TBChans.

TBChansDemo Modules and Files

Dec-20-2003
Thomas Breeden, tmb@virginia.edu

TBChansDemo   - Program: simple demo of TBChans and TextBlocks modules.
              - uses TBChans and TextIO procs to fill up the TextBlock
                from standard input, and "native" TextBlock procs to send the
                input lines to standard output in the reverse order.

TBChans       - ISO Std Channel I/O to memory.

TextBlocks    - in-memory, line-oriented, dynamically-extending blocks of text.

Dynamically allocated string processing
   DynStr0    - Basic procedures, size fixed at create time.
   DynStr1    - Common procedures
   DynStr1C   - Common procedures, one character parameter
   DynStr3    - As above, but size will be reallocated on assignment.

Null delimited static string processing
   Str0       - Basic procedures.

Debugging0    - Assert and Debug procs.

TBChansDemo Program

TBChansDemo is a very simple demo program of a user-written "device" with the ISO Standard channel IO procedures.

The underlying "device" is embodied in the modules TextBlocks and DynStr0 supporting in-memory text storage, and the ISO IOLink'd interface module TBChans.

The demo simply uses TBChans and TextIO procs to fill up the TextBlock from standard input, and "native" TextBlock procs to send the input lines to standard output in the reverse order.

eg, If the file Numbers.txt contains 1 through 5, one number on each line, the command

     TBChansDemo <Numbers.txt
produces the output
     5
     4
     3
     2
     1

NOTE:

  • It was written in the Stony Brook M2 v4 system. If you run it without redirecting standard input, type in a ^Z to force an endOfInput.
  • Module Debugging0's implementation is Windows specific.


(*###########################*)
 DEFINITION MODULE TextBlocks;    (* $VER: TextBlocks.def 0.0 (11.10.03) *)
(*###########################*)
                                       (* by Thomas Breeden, tmb@virginia.edu *)
(*
     TextBlocks are in-memory, line-oriented, dynamically-extending blocks
     of text. They can be written, read, and to some extent edited with this
     module.

     TextBlocks are layered on top of dynamic strings implemented by the
     DynStrX modules.
*)

(*
Copyright (C) 1997-2003 Thomas Breeden.

Permission to use, copy, modify and distribute this software and its
documentation for any purpose and without fee is hereby granted, provided that
the above copyright notice appear in all copies and that both the copyright
notice and this permission notice appear in supporting documentation.
Thomas Breeden makes no representations about the suitability of this software
for any purpose. It is provided "as is" without express or implied warranty.
*)

(* GoToMark should return BOOLEAN? *)

FROM DynStr0 IMPORT DynStr, DynStrPtr;

TYPE  TextBlock;

TYPE  MarkType = [0..4];

 PROCEDURE AllocBlock():TextBlock;
 PROCEDURE EmptyBlock(blk:TextBlock);
 PROCEDURE DeallocBlock(VAR blk:TextBlock);
       (* also does EmptyBlock *)

 PROCEDURE InvalidBlock():TextBlock;

(*------------------------------------*)
(* Writing Procedures *)

 PROCEDURE AppendBlockStr0(blk:TextBlock; VAR str:ARRAY OF CHAR);
 PROCEDURE AppendBlockdStr(blk:TextBlock; txt:DynStr);
 PROCEDURE AppendBlockChar(blk:TextBlock; ch:CHAR);
       (* The 3 procs above add text to the last line in the TextBlock, but dont
          create a new line (unless CF or LF or CRLF is embedded *)
 PROCEDURE NewBlockLine(blk:TextBlock);
 PROCEDURE AddBlockLine(blk:TextBlock; line:DynStr);
(* The 2 procs above first add a new line to the end
   of the TextBlock *)

 PROCEDURE AppendBlockLine(blk:TextBlock; appText:DynStr):BOOLEAN;
      (* append text to just read line *)
 PROCEDURE DeleteBlockLine(blk:TextBlock);
      (* delete the line just read *)
 PROCEDURE BeforeInsertBlockLine(blk:TextBlock; line:DynStr);
       (* sets "justread" to the inserted, and the reader to line after the inserted line *)
 PROCEDURE AfterInsertBlockLine(blk:TextBlock; line:DynStr);
       (* sets "justread" to the inserted, and the reader to line after the inserted line *)
 PROCEDURE ReplaceBlockLine(blk:TextBlock; line:DynStr);
(* The 5 procs above can act on text in the middle of the TextBlock. They act
   on the line "just read" *)

(*------------------------------------*)
(* Reading Procedures *)

 PROCEDURE ResetBlockRead(blk:TextBlock);
       (* sets the reader to before beginning, and "justread" to NIL *)
 PROCEDURE SetEndBlockRead(blk:TextBlock);
       (* sets the reader to beyond end, and the "justread" to end line *)

 PROCEDURE GetBlockTxt(blk:TextBlock; VAR dtxt:DynStr);
      (* This returns the entire TextBlock as one dynamic string line, with
         line separator replaced by space *)

 PROCEDURE NextBlockLine(blk:TextBlock; VAR line:DynStr):BOOLEAN;
 PROCEDURE PrevBlockLine(blk:TextBlock; VAR line:DynStr):BOOLEAN;
 PROCEDURE ReadBlockLine(blk:TextBlock; VAR line:DynStr):BOOLEAN;
 PROCEDURE GoToLine(blk:TextBlock; LineNum:CARDINAL; VAR line:DynStr):BOOLEAN;
       (* sequentially, from 0 *)
 PROCEDURE GotoMark(blk:TextBlock; WhichMark:MarkType; VAR line:DynStr);
(* The previous 6 procs copy text from the TextBlock to your dynamic string
   parameter. You must have called a dStrCreate() to initialize it. The memory
   it's .str pointer references may have be re-allocated on return *)

 PROCEDURE Mark(blk:TextBlock; WhichMark:MarkType);
      (* line just read is marked *)

 PROCEDURE NextBlockLineRef(blk:TextBlock; VAR line:DynStrPtr):BOOLEAN;
 PROCEDURE PrevBlockLineRef(blk:TextBlock; VAR line:DynStrPtr):BOOLEAN;
 PROCEDURE RefBlockLine(blk:TextBlock; VAR line:DynStrPtr):BOOLEAN;
 PROCEDURE GoToLineRef(blk:TextBlock; LineNum:CARDINAL; VAR line:DynStrPtr):BOOLEAN;
 PROCEDURE GotoMarkRef(blk:TextBlock; WhichMark:MarkType; VAR line:DynStrPtr);
(* The previous 5 procs do not copy text, but return a pointer into the TextBlock
   itself, which stores lines a dynamic strings. *)

(* NOTE:
      1. The Append... funcs will create a new block line on
         receiving a LF, CR, or CRLF.

      2. Adding a line with NewBlockLine(), AddBlockLine(), InsertAfterBlkLine(),
         or InsertBeforeBlkLine, always changes the reading state as if a
         NextBlockLine() had been done into the new line, no matter where the
         rdr was before.

      3. The ...Ref() procs can be much faster for getting at the text, but remember
         that the DynStr line belongs to the TextBlock, not you.

      4. GoToLine/Ref() is likely to be much slower than GotoMark/Ref().

VERSION HISTORY

    v0.0-052397     -first
        -052598     -Added GoToLine(), GoToLineRef(),Next/PrevBlockLineRef()

     0.0 (10.6.03) - unified StonyBrook and Benchmark versions. Added InvalidBlock() to
                     Benchmark version and changed LONGCARD to CARDINAL;
                     added NextBlockLineRef(), PrevBlockLineRef(),
                     GoToLine(), and GoToLineRef() to Stony Brook Version.

         (16.6.03) - Added GoToMarkRef()
         (4.7.03)  - Added RefBlockLine() and ReadBlockLine()
                   - "Fixed" all the Ref...() procs to return a DynStrPtr, so that
                     the caller can actually fiddle with the length of the dynstr in
                     the TextBlock, not just read it.

         (11.10.3) - Added AppendBlockLine()
*)

END TextBlocks.


 

The M2 ISO Standard I/O Architecture Manual
 
<Not yet written?>
<In the ISO Standard Document?>