Discussion:
emulation of Logitech 3.4 or PIM2 style I/O using ISO-m2 libraries
(too old to reply)
modsquad
2010-07-23 17:27:45 UTC
Permalink
Hello everyone:

Thanks for feedback on porting ISO libraries to Logitech 3.4 Modula-2.
I decided not to bother.

However, in the interest of portability, it turns out that it is
relatively simpler to emulate PIM2 or Logitech-style I/O using ISO
Modula-2 libraries.

I would like to submit the following Beta version of a command-line
filter for testing and feedback by the Modula-2 Group.

It filters text files delimited by CR LF pairs, or single CR or LF end-
of-line marks.

It needs testing and probably modification. It is O/S dependent since
it converts the output to CR LF. It also filters non-ASCII and control
characters other than CR or LF. Even horizontal tabs are filtered.

The filtering is not the main point of the example. That can easily be
modified.

I show how to hide the peculiarity of needing to SkipLine in the ISO
libraries when reading an end-of-line mark. I am attempting to treat
end-of-line as any other character by emulating the behavior of
Logitech and other PIM2 compatible I/O libraries when end-of-line is
read.

The ojective is not efficiency but to allow the running of programs
using PIM2 compatible Modula-2 I/O on ISO-only systems. The main point
is to simplify porting of PIM2-based m2 programs to ISO-based systems,
at least for those systems using InOut or perhaps Terminal or even
FileSystem.

I would appreciate feedback and bug reports on how it runs on various
ISO-based Modula-2 compilers. In particular, any needed modifications
to get it to run on Linux-based Modula-2 or other O/S with different
end-of-line conventions. Suggestions and improvements are welcome.

The command-line filter is supposed to handle:
1. named input files (output filenames are never to be specified)
2. redirection

MODULE ISOFilter4;

(*
Copyright © 2010 Carl Glassberg



Beta Version 23-July-2010, submitted for testing purposes to
Modula-2
user community. In particular I would like someone to test this
with
any ISO-compliant Modula-2 compilers, such as GNU m2.

The end-of-line handling is probably MSDOS-biased because it
converts
end-of-lines in the input to CR LF pairs. Also CreateOutputFN
procedure is
probably not robust across operating systems nor is it likely even
bug-free.

It might be safer to just append the output file extension to the
input
filename, keeping any existing input filename extension, although
output
filenames might become inconveniently long.

I welcome feedback and any bug reports or improvements, especially
those
that make it portable to Linux or other O/S with different end-of-
line
conventions.



This program is free software; you can redistribute it and/or modify
it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later
version.



This program is distributed in the hope that it will be useful, but
WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
details.



Write to
Free Software Foundation, Inc.
59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
or goto <http://www.gnu.org/licenses/gpl.html> for a copy of the
GNU General Public License.


(* ISOFilter4 cleans-up ASCII text files. *)



(* NOTE: uses ISO Modula-2 Input/Output. *)

(* end-of-line handling is O/S dependent. *)



(* Warning: This filter does not expand horizontal tabs--- a ht is
converted
to a single space. You may need to expand tabs to spaces before
running
this filter. *)



(* Filtering:

o Printable characters in the input are output unchanged.
printable char = (40C <= ch) & (ch <= 176C)


o Each control character (other than end-of-line)
and each character > 176C is converted to 1 space.



o end-of-line characters are converted as follows:

input: output:

cr lf ---> cr lf
cr ---> cr lf
lf ---> cr lf

*)



(*
--------------------------------------------------------------------------

usage: (command-line redirection from stdin/stdout)

1. isofilter4.exe < inputfile > outputfile



2. isofilter4.exe < inputfile (* output to the terminal *)

-----------------------------------------------------------------------------

usage: (no input/output filenames specified)

3. isofilter4.exe


Waits for of a line of keyboard input.
Keyboard input is echoed to the terminal.

After the user presses <Enter>, the input is filtered
and then output to the terminal on the next line.



Ctrl-C (Break) exits the program.



-----------------------------------------------------------------------------

or

usage:

4. isofilter4.exe inputfile1 { inputfile2 }
(* no output filename(s) are allowed *)
(no command-line redirection,
input filesname(s) specified as argument(s) to isofilter4)

-----------------------------------------------------------------------------

*)



IMPORT StreamFile, TextIO, IOResult, StdChans, ProgramArgs,

STextIO, SIOResult, Strings;

CONST

EOL = 36C; (* EOL is a control character not appearing in the
input *)



VAR

inf, outf : StreamFile.ChanId;

ifn, ofn : ARRAY[0..79] OF CHAR;

result : StreamFile.OpenResults;

ch : CHAR;





(* stdin/stdout: --------------------> *)



(* stdin: -----> *)



PROCEDURE done0() : BOOLEAN;

(* inspect input from stdin; return TRUE if not at end-of-file *)

BEGIN

RETURN (SIOResult.ReadResult() # SIOResult.endOfInput)

END done0;



PROCEDURE eol0() : BOOLEAN;

(* inspect input from stdin; return TRUE if at end-of-line *)

BEGIN

RETURN (SIOResult.ReadResult() = SIOResult.endOfLine)

END eol0;



PROCEDURE read_char0(VAR ch : CHAR);

(* input from stdin *)

BEGIN

STextIO.ReadChar(ch);

IF eol0() THEN ch := EOL; STextIO.SkipLine END (* if *)

END read_char0;



(* stdout: -----> *)



PROCEDURE write_char0(ch : CHAR);

(* output to stdout *)

BEGIN

IF (40C <= ch) & (ch <= 176C) THEN (* printable character *)

STextIO.WriteChar(ch)

ELSIF ch = EOL THEN

STextIO.WriteLn

ELSE (* (ch # EOL) & ((ch < 40C) OR (ch >= 177C)) *)
  (* any non-printing character (except EOL) is converted to
space: *)

STextIO.WriteChar(40C)

END (* if *)

END write_char0;



(* <----- end of stdin/stdout *)



(* stderr: -------------------------> *)



PROCEDURE WriteErrMsg(str: ARRAY OF CHAR);

(* output to stderr *)

BEGIN

TextIO.WriteString(StdChans.StdErrChan(), str)

END WriteErrMsg;



PROCEDURE WriteErrLn;

(* output to stderr *)

BEGIN

TextIO.WriteLn(StdChans.StdErrChan());

END WriteErrLn;



(* <----- end of stderr *)



(* i/o from/to named file: --------> *)



(* input from named file: *)



PROCEDURE done1() : BOOLEAN;

(* inspect input from named file; return TRUE if not at end-of-file
*)

BEGIN

RETURN (IOResult.ReadResult(inf) # IOResult.endOfInput)

END done1;



PROCEDURE eol1() : BOOLEAN;

(* inspect input from named file; return TRUE if at end-of-line *)

BEGIN

RETURN (IOResult.ReadResult(inf) = IOResult.endOfLine)

END eol1;



PROCEDURE read_char1(VAR ch : CHAR);

(* input from named file *)

BEGIN

TextIO.ReadChar(inf, ch);

IF eol1() THEN ch := EOL; TextIO.SkipLine(inf) END (* if *)

END read_char1;



(* output to named file: *)



PROCEDURE write_char1(ch : CHAR);

(* output to named file *)

BEGIN

IF (40C <= ch) & (ch <= 176C) THEN (* printable character *)

TextIO.WriteChar(outf, ch)

ELSIF ch = EOL THEN

TextIO.WriteLn(outf)

ELSE (* (ch # EOL) & ((ch < 40C) OR (ch >= 177C)) *)
  (* any non-printing character (except EOL) is converted to
space: *)

TextIO.WriteChar(outf, 40C)

END (* if *)

END write_char1;



(* <----- end of named file i/o *)





PROCEDURE CreateOutputFN(VAR outputfilename : ARRAY OF CHAR (*
output *);

inputfilename : ARRAY OF CHAR (* input
*);

ext : ARRAY OF CHAR (* input
*));



(*

if inputfilename has no file extension, then
outputfilename := inputfilename + "." + ext,

otherwise
the rightmost file extension and
preceding "." is deleted from inputfilename

when constructing the outputfilename.



Input (or output) filenames beginning with "." are not allowed.



Example:

inputfilename: file.txt

ext: new

outputfilename: file.new

*)



VAR n, pos : CARDINAL; found: BOOLEAN;

BEGIN

outputfilename[0] := 0C;

n := Strings.Length(inputfilename);

IF n > 0 THEN

pos := 0;

Strings.FindPrev('.', inputfilename, n-1, found, pos);

IF found THEN

IF (inputfilename[0] # ".") THEN

Strings.Extract(inputfilename, 0, pos, outputfilename);

Strings.Append('.', outputfilename);

Strings.Append(ext, outputfilename)

ELSE

WriteErrLn; WriteErrMsg('filename beginning with "." not
allowed: ');

WriteErrMsg('('); WriteErrMsg(inputfilename);
WriteErrMsg(')')

END (* if *)

ELSE (* no extension *)

Strings.Concat(inputfilename, '.', outputfilename);

Strings.Append(ext, outputfilename)

END (* if *)

END (* if *)

END CreateOutputFN;



BEGIN

IF ProgramArgs.IsArgPresent() THEN

(* command-line arguments are named input files: *)

LOOP

TextIO.ReadToken(ProgramArgs.ArgChan(), ifn);

StreamFile.Open(inf, ifn, StreamFile.read, result);

IF result # StreamFile.opened THEN

WriteErrLn; WriteErrMsg('Could not open input file: ');
WriteErrMsg(ifn);

EXIT

END (* if *);



CreateOutputFN(ofn, ifn, "new");

StreamFile.Open(outf, ofn, StreamFile.write, result);

IF result = StreamFile.fileExists THEN

WriteErrLn; WriteErrMsg('output file: ');
WriteErrMsg(ofn); WriteErrMsg(' already exists!');

IF result = StreamFile.opened THEN

StreamFile.Close(outf)

END (* if *);

ELSE (* ofn is a new output file *)

IF result # StreamFile.opened THEN

WriteErrLn; WriteErrMsg('Could not open output file: ');
WriteErrMsg(ofn);

EXIT

END (* if *);



read_char1(ch);

WHILE done1() DO

write_char1(ch);

read_char1(ch);

END (* while *);



StreamFile.Close(inf);

StreamFile.Close(outf);



END (* if *);

ProgramArgs.NextArg();

IF NOT(ProgramArgs.IsArgPresent()) THEN EXIT END (* if *);

END (* loop *)

ELSE

(* stdin/stdout with command-line redirection: *)

read_char0(ch);

WHILE done0() DO

write_char0(ch);

read_char0(ch);

END (* while *);

END (* if *);



END ISOFilter4 .
modsquad
2010-07-23 22:53:48 UTC
Permalink
Hello again:
Apologies for how the line formatting turned out when posted.
It looked fine in the Google web-based message composer tool, but
unintendted extra end-of-line wrapping occurred.

Ironic for an example text file filter that is supposed to convert end-
of-lines that I couldn't even get it to look right.
Post by modsquad
Thanks for feedback on porting ISO libraries to Logitech 3.4 Modula-2.
I decided not to bother.
However, in the interest of portability, it turns out that it is
relatively simpler to emulate PIM2 or Logitech-style I/O using ISO
Modula-2 libraries.
I would like to submit the following Beta version of a command-line
filter for testing and feedback by the Modula-2 Group.
It filters text files delimited by CR LF pairs, or single CR or LF end-
of-line marks.
It needs testing and probably modification. It is O/S dependent since
it converts the output to CR LF.
cmg: [it converts input end-of-line marks to CR LF on output]
Post by modsquad
The ojective is not efficiency but to allow the running of programs
cmg:[objective]
Post by modsquad
using PIM2 compatible Modula-2 I/O on ISO-only systems. The main point
is to simplify porting of PIM2-based m2 programs to ISO-based systems,
at least for those systems using InOut or perhaps Terminal or even
FileSystem.
cmg: [correction: at least for m2 programs using InOut, Terminal, or
even FileSystem]

Sorry
Modulan1
The ModSquad
Objective Modula-2
2010-07-24 07:57:31 UTC
Permalink
Post by modsquad
I would like to submit the following Beta version of a command-line
filter for testing and feedback by the Modula-2 Group.
I'd like to encourage you to set up a public repository and put your
code in there. There are many repository services available that offer
free accounts for open source projects. Perhaps the most commonly
known ones are Bitbucket, Github, GoogleCode and Sourceforge
(alphabetic order). Bitbucket supports online syntax colouring for
Modula-2 sources, and there are a few Modula-2 projects on the site:

http://bitbucket.org/repo/all?name=Modula-2

GoogleCode doesn't seem to do syntax colouring but it has a few
Modula-2 projects, most of them are graduation projects:

http://code.google.com/hosting/search?q=Modula-2&btn=Search+projects

If you publish your code in this way, it will get decent exposure
because these sites have high page rankings at Google and other search
engines. It helps others to find and easily inspect your code without
even having to download it. It also raises the profile of Modula-2 as
a whole if more Modula-2 code shows up in well known public
repositories.

Once you have set up a repository and uploaded your code, you can
register the URL to your repository with Ohloh.net, a site that tracks
open source projects and generates statistics. Ohloh has support for
Modula-2 sources (=> it knows how to count code and comments) and
there are quite a few Modula-2 projects already being tracked:

http://www.ohloh.net/p?sort=users&q=Modula-2

Loading...