Mise-à-jour: 25 Octobre 1995

mylib

A Small General Purpose Modula-2 Library

Pierre L’Ecuyer

Département d’IRO Université de Montréal

Résumé

This document describes a set of modules in the language Modula-2, which have been written to improve the portability of Modula-2 programs. These modules have been implemented under different environments, including MS-DOS, SUN/OS and Solaris. The reason why we wrote mylib is because the libraries which come with different compilers are often very different. Even the names of the procedures which perform standard operations such as input/output or standard mathematical functions are often different. The role of mylib is to make a standard interface between a modula-2 programmer and his programming environment.

MYINOUT

This module offers basic input/output facilities. It has been implemented in different environments and the aim is to improve portability. It is somewhat similar to the module InOut described in Wirth’s book, with some additions. One major difference with InOut, though, is that here, after reading an item which is at the end of a line, the system does not read automatically the “Line feed” or “carriage return”. An explicit ReadLn must be performed to go to the next line. Also, if any reading operation is attempted while at the end of a line, the system will not go to the next line automatically.

Reads and writes are made from and to the defaults input and output devices. Initially, both correspond to the terminal (unless input and/or output is redirected from outside). The default input file can be changed using OpenInput, OpenAsInput, or SetInput, while the default output can be changed using OpenOutput, OpenAsOutput, or SetOutput. The current default input and output file can be obtained by calling GetInput and GetOutput, respectively.

DEFINITION MODULE MYINOUT;
(* FROM Files IMPORT File;                                 VERSION SUN *)
FROM FileIO IMPORT FILE;                                   (*  SOLARIS *)
FROM NUM    IMPORT LONGCARD;                               (*  SOLARIS *)
VAR
   OK : BOOLEAN;

Is set to TRUE when last input/output operation has succeeded, and to FALSE otherwise.

PROCEDURE OpenInput  (Ext : ARRAY OF CHAR);

Asks for the name of a text file, without extension, interactively at the terminal. The extension “Ext”, which should start with a “.”, will be added to that name. Then that file will be opened and will become the default input file. For example, OpenInput (".dat") asks for a file name f and opens f.dat as the input file.

PROCEDURE OpenOutput (Ext : ARRAY OF CHAR);

Similar to OpenInput. Asks for the name of a text file, without extension, interactively at the terminal. The extension “Ext” (starting with a dot) will be added to that name. This file will then be opened (and created, if necessary) and will become the default output file.

PROCEDURE OpenAsInput  (S : ARRAY OF CHAR);

The file whose name is given by S is opened and becomes the default input file.

PROCEDURE OpenAsOutput (S : ARRAY OF CHAR);

The file whose name is given by S is opened (and created, if necessary) and becomes the default output file.

October 25, 1995 MYINOUT 2

PROCEDURE CloseInput;

Closes the default input file. Standard input becomes the new default.

PROCEDURE CloseOutput;

Closes the default output file. Standard output becomes the new default.

PROCEDURE SetInput (f : FILE);

Sets the default input to f.

PROCEDURE SetOutput (f : FILE);

Sets the default output to f.

PROCEDURE GetInput (VAR f : FILE);

Returns the default input file in variable f.

PROCEDURE GetOutput (VAR f : FILE);

Returns the default output file in variable f.

PROCEDURE EOL () : BOOLEAN;

Returns TRUE if the last reading operation failed because we were at the end of a line. Otherwise, returns FALSE.

PROCEDURE EOF () : BOOLEAN;

Returns TRUE if the last reading operation failed because we were at the end of the input file. Otherwise, returns FALSE.

PROCEDURE ReadLn;
PROCEDURE Read         (VAR C : CHAR);
PROCEDURE ReadBool     (VAR B : BOOLEAN);
PROCEDURE ReadInt      (VAR x : INTEGER);
PROCEDURE ReadCard     (VAR x : CARDINAL);
PROCEDURE ReadLongInt  (VAR x : LONGINT);
PROCEDURE ReadLongCard (VAR x : LONGCARD);
PROCEDURE ReadReal     (VAR x : REAL);
PROCEDURE ReadLongReal (VAR x : LONGREAL);
PROCEDURE ReadString   (VAR S : ARRAY OF CHAR);

Reads up to the next separator like blank or end-of-line.

PROCEDURE ReadLine     (VAR S : ARRAY OF CHAR);

Reads up to the end-of-line (including the blanks).

PROCEDURE WriteLn;
PROCEDURE Write         (C : CHAR);
PROCEDURE WriteString   (S : ARRAY OF CHAR);
PROCEDURE WriteBool     (B : BOOLEAN);
PROCEDURE WriteInt      (x : INTEGER;  n : CARDINAL);
PROCEDURE WriteCard     (x, n : CARDINAL);
PROCEDURE WriteLongInt  (x : LONGINT;  n : CARDINAL);
PROCEDURE WriteLongCard (x : LONGCARD;  n : CARDINAL);
PROCEDURE WriteReal     (x : REAL;  p : CARDINAL;  i : INTEGER);
PROCEDURE WriteLongReal (x : LONGREAL;   p : CARDINAL;  i : INTEGER);

For WriteReal and WriteLongReal, uses p positions in total, and i of those are for the decimal places. There will be no point if i = 0 and scientific notation is used if i < 0.

END MYINOUT.

NUM

This module offers some basic tools to manipulate numbers represented in different forms. It duplicates many basic facilities offered with typical compilers. Its purpose is to enhance portability. It offers the most oftenly used facilities. Double precision (64-bit) floating point numbers are called LONGREAL, while 32-bit integers are called LONGINT and LONGCARD. These types might be actually “defined” differently in the definition module for different implementations.

DEFINITION MODULE NUM;
FROM SYSTEM IMPORT UNSIGNED_32;                            (*  SOLARIS *)
TYPE
LONGCARD  =  UNSIGNED_32;                               (*  SOLARIS *)
CONST
MaxLongInt       = 2147483647;
LgMaxLongInt1    = 31;              (* Log (MaxLongInt+1) in base 2. *)
t                = 53;              (* Precision in LONGREAL,        *)
                                   (* - 53 for SUN ; 52 for PC's  - *)
MaxTwoExp        = 64;              (* All powers of 2 are represen- *)
                                   (* ted exactly in LONGREAL !     *)
VAR
(* These should be constants, but some compilers do not allow it.    *)
MaxLongIntLR,                       (* = MaxLongInt, in LONGREAL.    *)
MaxIntLongReal,                     (* Max. value represented        *)
                                   (* exactly as a LONGREAL.        *)
MaxLongReal,                        (* Max. value for a LONGREAL.    *)
ZeroLR,                             (* = 0.                          *)
Point5LR,                           (* = 0.5.                        *)
OneLR,                              (* = 1.                          *)
TwoLR,                              (* = 2.                          *)
ThreeLR,                            (* = 3.                          *)
FourLR : LONGREAL;                  (* = 4.                          *)
TwoExp : ARRAY[0..MaxTwoExp] OF LONGREAL;  (* TwoExp[i] = 2^i.       *)
hLR,                                (* 2^{-t}                        *)
chLR,                               (* 1 - hLR                       *)
jLR    : LONGREAL;                  (* hLR + hLR/2                   *)

PROCEDURE S (x : LONGREAL) : LONGREAL;

If x > 0, returns the smallest LONGREAL representable on the machine and strictly greater than x. Verifies S(0) = 0 and S(−x) = −S(x). This can be used to compute bounds on the numerical errors in floating-point arithmetic.

PROCEDURE Pow (x, y : LONGREAL) : LONGREAL;

Returns x^{y}.

PROCEDURE Sqrt (x : LONGREAL) : LONGREAL;

Returns \sqrt{x}.

October 25, 1995 NUM 5

PROCEDURE Exp (x : LONGREAL) : LONGREAL;

Returns e^{x}.

PROCEDURE Ln (x : LONGREAL) : LONGREAL;

Returns Ln(x).

PROCEDURE Lg (x : LONGREAL) : LONGREAL;

Returns Log_{2}(x).

PROCEDURE Sin (x : LONGREAL) : LONGREAL;

Returns sin(x).

PROCEDURE Cos (x : LONGREAL) : LONGREAL;

Returns cos(x).

PROCEDURE IToLI (i : INTEGER) : LONGINT;

Returns the LONGINT representation of i.

PROCEDURE IToLR (i : INTEGER) : LONGREAL;

Returns the LONGREAL representation of i.

PROCEDURE LIToLR (i : LONGINT) : LONGREAL;

Returns the LONGREAL representation of i.

PROCEDURE LCToLR (c : LONGCARD) : LONGREAL;

Returns the LONGREAL representation of c.

PROCEDURE REALToLR (x : REAL) : LONGREAL;

Returns the LONGREAL representation of x.

PROCEDURE StringToLR (S : ARRAY OF CHAR) : LONGREAL;

Returns the LONGREAL representation of S, viewed as a string of decimal digits.

PROCEDURE StringToLI (S : ARRAY OF CHAR) : LONGINT;

Returns the LONGINT representation of S, viewed as a string of decimal digits.

PROCEDURE ModLR (x, y : LONGREAL) : LONGREAL;

Returns x mod y, which is in the interval [0, y). Must have y > 0 and ⌊x/y⌋ must be representable as a LONGINT.

PROCEDURE TruncLR (x : LONGREAL) : LONGREAL;

Returns the truncated (integer) value of x. Truncates towards 0. For example, TruncLR (-1.6) will return -1.0. If that truncated value cannot be represented exactly as a LONGREAL, writes an error message.

PROCEDURE RoundLR (x : LONGREAL) : LONGREAL;

Returns the rounded (integer) value of x. If that rounded value cannot be represented exactly as a LONGREAL, writes an error message.

PROCEDURE Trunc (x : LONGREAL) : LONGINT;

Returns the truncated value of x. Truncates towards 0. For example, Trunc (-1.6) will return -1. If that truncated value cannot be represented as a LONGINT, writes an error message and stops the program.

PROCEDURE Round (x : LONGREAL) : LONGINT;

Returns the nearest integer to x. If that rounded value cannot be represented as a LONGINT, writes an error message and stops the program.

PROCEDURE ReadLI (VAR i : LONGINT);
PROCEDURE ReadLC (VAR c : LONGCARD);
PROCEDURE ReadLR (VAR x : LONGREAL);
PROCEDURE WriteLI (i : LONGINT;  s : CARDINAL);

Writes i to current output. Uses at least s spaces.

PROCEDURE WriteLC (c : LONGCARD;  s : CARDINAL);

Writes c to current output. Uses at least s spaces.

PROCEDURE WriteLR (x : LONGREAL;  I, J, K : CARDINAL);

Writes x to current output. Uses a total of at least I positions (including the sign and point when they appear), J digits after the decimal point and at least K significant digits. J and K must be strictly smaller than I. The number is rounded if necessary. If there is not enough space to print the number in decimal notation with at least K significant digits (J or I is too small), it will be printed in scientific notation with at least K significant digits. In that case, I is increased if necessary.

END NUM.

MYSTR

This module offers some tools for the manipulation of character strings. It is basically the same as the module Str of TopSpeed Modula-2.

DEFINITION MODULE MYSTR;
(* TYPE CHARSET = SET OF CHAR;                             VERSION SUN *)
FROM SYSTEM  IMPORT UNSIGNED_16;
CONST                                                      (*  SOLARIS *)
   maxcharsinset= 1024;
   bits= 32;            (* VAX *)(* bits= 16; (* PDP *) *)
   words= maxcharsinset DIV bits;
TYPE
   CharSet= ARRAY[ 0.. words- 1] OF BITSET;                (*  SOLARIS *)
 (* A 16/32 bit machine is assumed. A set of 256 characters is implemented. *)
VAR s0: CharSet; (* empty set *)                           (*  SOLARIS *)

PROCEDURE Append (VAR Res: ARRAY OF CHAR;
                  Source : ARRAY OF CHAR);

Appends the string Source at the end of the string Res.

PROCEDURE Caps (VAR Source : ARRAY OF CHAR);

Converts all lowercase letters in the string Source to uppercase.

PROCEDURE Compare (S1, S2: ARRAY OF CHAR): INTEGER;

Compares two strings from left to right until a difference is found. If S1 is equal to S2, it returns 0. If S1 is less than S2, it returns -1. If S1 is greater than S2, it returns 1.

PROCEDURE Concat (VAR Res : ARRAY OF CHAR;
                  S1, S2  : ARRAY OF CHAR);

Concatenates S1 and S2, and returns the result in Res.

PROCEDURE Copy (VAR Dest : ARRAY OF CHAR;
                Source   : ARRAY OF CHAR);

Copies the string Source into Dest.

PROCEDURE Delete (VAR S : ARRAY OF CHAR;
                  index : CARDINAL;
                  len   : CARDINAL);

Deletes len characters from S, starting at position index.

October 25, 1995 MYSTR 8

PROCEDURE Insert (VAR Res : ARRAY OF CHAR;
               Source  : ARRAY OF CHAR;
               Pos     : CARDINAL);

Inserts the string Source into Res, starting at position Pos.

PROCEDURE Item (VAR R : ARRAY OF CHAR;
             S     : ARRAY OF CHAR;
             T     : CharSet;
             N     : CARDINAL);

Returns in R the N-th substring of S (counting from 0). Substrings are delimited by any character from the set T.

PROCEDURE ItemS (VAR R : ARRAY OF CHAR;
              S     : ARRAY OF CHAR;
              T     : ARRAY OF CHAR;
              N     : CARDINAL      );

Same as Item, except that delimiters are in the array T.

PROCEDURE Length (S : ARRAY OF CHAR): CARDINAL;

Returns the length of the string S.

PROCEDURE Match (Source, Pattern : ARRAY OF CHAR) : BOOLEAN;

Returns TRUE if the string Source matches the string Pattern, and FALSE otherwise. The characters “?” and “*” are recognized as wild characters in the string Pattern.

PROCEDURE Slice (VAR R: ARRAY OF CHAR;
              S    : ARRAY OF CHAR;
              P, L : CARDINAL);

Returns in R the substring in S beginning at position P and of length L.

PROCEDURE Subst (VAR Source : ARRAY OF CHAR;
              OldPattern : ARRAY OF CHAR;
              NewPattern : ARRAY OF CHAR);

Searches for the string OldPattern in the string Source, and replaces its first occurence with

NewPattern.
PROCEDURE Position (Substring  : ARRAY OF CHAR;
                 Source     : ARRAY OF CHAR;
                 at         : CARDINAL;
                 VAR pos    : UNSIGNED_16;
                 VAR found  : BOOLEAN );

Searches for the string Substring in the string Source, starting at position at, and returns the position of its first occurence in pos.

PROCEDURE StrToInt
   (S : ARRAY OF CHAR;  b : INTEGER;  VAR OK : BOOLEAN) : LONGINT;

Returns the LONGINT representation of S, assuming that S is written in base b. (Note: on the SUN, one must have b = 10.)

(********************** SET OF CHAR (SOLARIS)**********************)
PROCEDURE set (VAR s: CharSet;
          ch   : CHAR);
PROCEDURE setn (VAR s: CharSet;
           ch   : ARRAY OF CHAR);
PROCEDURE inset (VAR s: CharSet;
            ch   : CHAR): BOOLEAN;
PROCEDURE insetn (VAR s: CharSet;
             ch   : ARRAY OF CHAR): BOOLEAN;
PROCEDURE addset (VAR s,s1,s2: CharSet);
PROCEDURE inclset (VAR s,s1: CharSet);
PROCEDURE subset (VAR s,s1,s2: CharSet);
PROCEDURE exclset (VAR s,s1: CharSet);
PROCEDURE genset (VAR s,s1: CharSet;
             ch      : CHAR);
PROCEDURE gensetn (VAR s,s1: CharSet;
              ch      : ARRAY OF CHAR);
PROCEDURE InCharSet (CH: CHAR;
                S :  CharSet): BOOLEAN;
(*  InCharSet is true if and only if CH belongs to S. *)
PROCEDURE CharSetUnion (A    : CharSet;
                   B    : CharSet;
                   VAR C: CharSet);
(* C becomes the union of A and B. *)
PROCEDURE CharSetDifference (A    : CharSet;
                        B    : CharSet;
                        VAR C: CharSet);
(* C becomes the set difference of A and B  (C=  A`B). *)
PROCEDURE CharSetIntersection (A    : CharSet;
                         B    : CharSet;
                         VAR C: CharSet);
(* C becomes the intersection of A and B. *)
PROCEDURE CharSetSymmetricDifference (A    : CharSet;
                                B    : CharSet;
                                VAR C: CharSet);
(* C becomes the symmetric differende of A and B. *)
PROCEDURE DefineCharSet (Constructor    : ARRAY OF CHAR;
                    VAR S          : CharSet;
                    VAR ErrorNumber: CARDINAL);
(*  Defines the set of characters S by means of Constructor.
The syntax of Constructor in EBNF notation is:
Set=            ElementarySet {',' ElementarySet}
ElementraySet=  [ PointSet [ '..' PointSet ] ]
PointSet=       '(' CHAR ')' | '[' Number ']'
Number=         [ Digit ] [ Digit ] Digit
The meanings of PointSet and ElementarySet are:
PointSet
a set with one element.  As an instance both (0) and [48] denote
the character '0', if the ordinals follow the ASCII convention.
ElementarySet
a simply connecetd set of characters.  As an instance [49]..[55] or
(1)..(7) or [49]..(7) or (1)..[55] all denote the set of all characters
between '1' and '7'.
Remark: blank, which are not enclosed in parentheses are ignored.
Examples:
DefineCharSet('(a), (f), (r)..(z)', S, ErrorNumber) defines S as
the set containing the characters 'a', 'f' and all characters
between 'r' and 'z'.
DefineCharSet('[48]..[57], ( ), (A)..(Z), (.)', S, ErrorNumber) defines
S as the set of all numerals, blank, all upper case characters and
the point.
ErrorNumber reports errors which occur when Constructor does not
follow the syntax, given above.
0)   No error
1)   Extra garbage in Constructor.
2)   Two points are required to separate PointSets when building
     an ElementarySet.
3)   Unexpected end of Constructor.
4)   ) Expected.
5)   ] Expected.
6)   Digit expected.
7)   Number too large.
*)
END MYSTR.

MYPARAM

Gives a procedure for accessing the arguments of the current command line.

DEFINITION MODULE MYPARAM;
PROCEDURE ParamToString (N : CARDINAL;   VAR S : ARRAY OF CHAR);

Returns in S the N-th parameter of the command line. For example, if the command line is “myprog one two three” and N = 2, then S will contain “two”. If there is no N-th parameter or if S is too small, then an error message is written to the default output and the program is stopped.

END MYPARAM.

CLib.c

Ce module est une librairie de fonctions écrites dans le langage C.

La fonction Heure donne accès au temps de CPU consommé par le programme depuis le début de son exécution.

Les fonctions LRealToStr et StrToLReal s’occupe de la conversion de nombre réels (long) en chaîne de caractères et vice-versa.

L’appel à ces fonctions se fait exactement comme pour les fonction dans les librairies Modula-2. Il est à noter que la compilation d’un programme appelant une ou plusieurs de ces fonctions (directement ou indirectement par le biais d’une autre procédure), doit se faire de la manière suivante :

mc -l:/home/matawin/stochas/mcslib/libmylib.a ml -l:/home/matawin/stochas/mcslib/libmylib.a

-llib:/home/matawin/stochas/mylib/mcs/clib.o:-lc -cfg:c

Options de compilation

-case : pour l’utilisation de majuscules dans les noms de module;

-s : pour l’utilisation du debugger gdb;

-errtxt : pour afficher les erreurs sous format texte;

-lnam:/usr/ucb/ld : pour utiliser un linker plus efficace.

INTERFACE MODULE CLib;
PROCEDURE Heure  EXTERNAL heure (VAR sec : CARDINAL; VAR usec : CARDINAL);

”sec” retourne les secondes et ”usec” les microsecondes.

PROCEDURE StrToLReal EXTERNAL stolreal
 (
  S : ARRAY OF CHAR;
  VAR x : LONGREAL
  );
PROCEDURE LRealToStr EXTERNAL lrealtos
  (
   x : LONGREAL;
   i : INTEGER;
   VAR S : ARRAY OF CHAR
   );
END CLib.

CHRONO

CHRONO est un petit module qui fait l’interface avec l’horloge de l’ordinateur, et sert à chronométrer l’exécution de certaines parties d’un programme.

On peut faire fonctionner plusieurs chronomètres simultanément. Pour chaque chronomètre que l’on veut utiliser, on doit déclarer une variable de type Chrono. La procédure InitChrono permet d’initialiser ou de réinitialiser un chronomètre à zéro. Les types TimeFormat et Time-Unit, prédéfinis dans le module, permettent de choisir les unités de temps utilisées. La valeur du temps de CPU consommé par le programme depuis son dernier appel à InitChrono, pour un chronomètre donné, peut être imprimée dans le fichier de sortie courant par la procédure WriteChrono, ou retournée à l’usager par la procédure ValChrono. La précision est de l’ordre de 10 msec sous VAX/VMS et de 60 msec sous MS-DOS. Evidemment, la valeur retournée inclut une partie du temps d’exécution des procédures du module CHRONO.

Sous Unix (Solaris 2.3 Mcs), toute procédure utilisant ce module (directement ou non) doit

être compilée de la facon suivante : ml nom -llib:/home/matawin/martinb/mcs/heure.o

DEFINITION MODULE CHRONO;
TYPE
(* SUN   Chrono
                                 (*  SOLARIS *)
     RECORD
       microsec : CARDINAL;
       second   : CARDINAL;
     END;

Un chronomètre. Pour chaque chronomètre qu’il veut utiliser, l’usager doir déclarer une variable de ce type, puis l’initialiser en appelant InitChrono.

   TimeFormat = (sec, min, hours, days, hms);

Lors de chaque consultation de chronomètre, l’usager spécifie s’il désire obtenir une mesure en secondes (sec), en minutes (min), en heures (hours) ou en jours (days). Lorsqu’on fait imprimer la valeur du chronomètre, on peut aussi demander le format hms, et le temps apparaitra sous la forme HH:MM:SS.xx indiquant les heures, minutes, secondes et centièmes de secondes.

   TimeUnit = [sec..days];

Une unité de mesure du temps.

PROCEDURE InitChrono (VAR C : Chrono);

Initialise le chronomètre C à zéro.

October 25, 1995 CHRONO 13

PROCEDURE ValChrono
( C    : Chrono;
  Unit : TimeUnit
) : LONGREAL;

Retourne, selon l’unité Unit, le temps CPU consommé par le programme appelant depuis son dernier appel à InitChrono pour le chronomètre C.

PROCEDURE WriteChrono
( C    : Chrono;
  Form : TimeFormat
);

Imprime, dans le fichier de sortie courant, selon l’unité ou le format Form, le temps CPU consommé par le programme appelant depuis son dernier appel à InitChrono pour le chronomètre

C.
END CHRONO.

tcode

Le programme tcode permet de produire du code compilable à partir d’une documentation destinée à TEX ou LATEX. Il produit un fichier FOut destine a un compilateur tel que Modula-2 (ou autre), à partir d’un fichier FIn reçu à l’entrée. Les noms de ces deux fichiers sont donnés par l’usager, avec l’extension, lors de l’appel du programme. N’apparaitront dans le second fichier que les parties se trouvant entre les delimiteurs \code et \endcode. Toutes les autres commandes TEX et LATEX, même à l’intérieur de ces délimiteurs, seront aussi enlevées. L’appel se fait sous la forme:

tcode ⟨FIn⟩ ⟨FOut⟩

Les deux noms de fichiers (avec l’extension) doivent être différents. Par exemple, si le fichier destiné à LATEX est CHRONO.tex et que l’on veut en extraire le code compilable et placer ce dernier dans CHRONO.def (module de définition), on fera:

                       tcode  CHRONO.tex  CHRONO.def