# Utility libraries

Starting from XDS v2.0 the general purpose modules used in XDS compilers and utilities, which are portable between all versions of XDS on all platforms, are included in the utility library. If you use the ISO library only, your program may be portable to any ISO compliant Modula-2 compiler. However, there are some essential features which are omitted in the ISO library. The utility library covers some of those omissions.

Note: Some library modules are written in Oberon-2, others in Modula-2. In general, any library can be used from both languages. However, do not forget that Oberon modules use implicit memory deallocation scheme and require garbage collection. Refer to the Multilangauge programming Chapter of the XDS User's Guide.

The following modules are provided in the utility library (implementation language is pointed out in parentheses):

`FileName` | (M2) | Creating and parsing file names
`FileSys` | (M2) | Common file operations
`FormOut` | (M2) | Generic module for formatting output
`FormStr` | (M2) | Formatting output to strings
`Printf` | (M2) | C style formatting output precedures
`ProgEnv` | (M2) | Access to program environment
`TimeConv` | (M2) | Operations on time and date values
`DStrings` | (O2) | Dynamic strings
`FilePath` | (O2) | File search operations
`RegComp` | (O2) | Regular expressions

- FileName module
- FileSys module
- FormOut module
- FormStr module
- Printf module
- ProgEnv module
- TimeConv module
- DStrings module
- FilePath module
- RegComp module

## FileName module

The module provides operations for parsing and constructing file names. A file name consists of three parts: the directory, name and extension.

All the procedures that construct a string value (`Get`, `GetDir`, `GetName`, `GetExt`, `Convert`, `Create`), have the common behaviour: if the length of a constructed string value exceeds capacity of a variable parameter, a truncated value is assigned. If the length of a constructed string value is less than the capacity of a variable parameter, a string terminator is appended.

- Format - File name format record
- GetFormat - Get file name format
- Get* - Get file name parts
- Convert - Convert String to File Name
- ConvertExt - Convert File Name Extension
- Length - Calculate File Name Length
- Create - Create File Name
- Example

### Format - File name format record

    TYPE
      Format = RECORD
        ok: BOOLEAN;
        (* directory position and length: *)
        dirPos, dirLen : CARDINAL;
        (* name position and length: *)
        namePos,nameLen: CARDINAL;
        (* extension position and length: *)
        extPos, extLen : CARDINAL;
      END;

Module `FileName`

### GetFormat - Get file name format

    PROCEDURE GetFormat(str: ARRAY OF CHAR; VAR f: Format);

Module `FileName`

The `GetFormat` procedure writes the position and length of file name parts to a `Format` type record passed in `f`. If `f.ok = FALSE`, vaues of all other fields are undefined.

### Get* - Get file name parts

    PROCEDURE GetDir (fname: ARRAY OF CHAR;
                    VAR dir: ARRAY OF CHAR);
    PROCEDURE GetName(fname: ARRAY OF CHAR;
                   VAR name: ARRAY OF CHAR);
    PROCEDURE GetExt (fname: ARRAY OF CHAR;
                    VAR ext: ARRAY OF CHAR);
    PROCEDURE Get(fname: ARRAY OF CHAR;
       VAR dir,name,ext: ARRAY OF CHAR);

Module `FileName`

These procedures return corresponding file name parts.

### Convert - Convert String to File Name

    PROCEDURE Convert(str: ARRAY OF CHAR;
                VAR fname: ARRAY OF CHAR);

Module `FileName`

Converts a string to a file name according to the conventions of the underlying file system.

### ConvertExt - Convert File Name Extension

    PROCEDURE ConvertExt(VAR ext: ARRAY OF CHAR);

Module `FileName`

Converts an extension according to the conventions of the underlying file system.

### Length - Calculate File Name Length

    PROCEDURE Length(dir,name,ext: CARDINAL): CARDINAL;

Module `FileName`

Using the lengths of the directory, name and extension returns an estimated file name length which is greater than or equal to the length of the name generated by the `Create` procedure call.

### Create - Create File Name

    PROCEDURE Create(dir,name,ext: ARRAY OF CHAR;
                        VAR fname: ARRAY OF CHAR);

Module `FileName`

Creates a file name from its parts.

### Example

The following procedure can be used to change file name extension:

    PROCEDURE ChangeExt(VAR fname: ARRAY OF CHAR;
                           newext: ARRAY OF CHAR);
      CONST Len = 64;
      VAR
        dir,name: ARRAY [0..Len-1] OF CHAR;
        f: FileName.Format;
        len: CARDINAL;
    BEGIN
      FileName.GetFormat(fname,f);
      IF NOT f.ok THEN Error("wrong format")
      ELSIF (f.dirLen > Len) OR (f.nameLen > Len) THEN
        Error("too long part");
      ELSE
        len:=FileName.Length(f.dirLen,f.nameLen,LENGTH(newext));
        IF len-1 > HIGH(fname) THEN
          Error("cannot create file name")
        ELSE
          FileName.Create(dir,name,newext,fname);
        END;
      END;
    END ChangeExt;

When programming in Oberon-2 dynamic strings can be used to create strings of a required length:

    PROCEDURE ChangeExt(VAR fname: ARRAY OF CHAR;
                           newext: ARRAY OF CHAR);
      VAR
        dir,name: DStrings.String;
        f: FileName.Format;
    BEGIN
      FileName.GetFormat(fname,f);
      IF NOT f.ok THEN Error("wrong format")
      ELSE
        NEW(dir,f.dirLen+1);
        NEW(name,f.nameLen+1);
        ...
        END;
      END;
    END ChangeExt;

## FileSys module

The module provides file common operations.

- Exists - Is File Exist
- ModifyTime - Return Modify Time
- Rename - Rename File
- Remove - Remove File

### Exists - Is File Exist

    PROCEDURE Exists(fname: ARRAY OF CHAR): BOOLEAN;

Module `FileSys`

Returns `TRUE`, if file `fname` exists.

### ModifyTime - Return Modify Time

    PROCEDURE ModifyTime(fname: ARRAY OF CHAR;
                      VAR time: LONGCARD;
                    VAR exists: BOOLEAN);

Module `FileSys`

Returns a file modification time; `time` is valid only if `exists=TRUE`.

### Rename - Rename File

    PROCEDURE Rename(fname,newname: ARRAY OF CHAR;
                          VAR done: BOOLEAN);

Module `FileSys`

Renames the file `fname` to `newname`.

### Remove - Remove File

    PROCEDURE Remove(fname: ARRAY OF CHAR;
                  VAR done: BOOLEAN);

Module `FileSys`

Removes a file.

## FormOut module

The `FormOut` module implements a generic formatted output procedure which outputs its arguments according to the format parameter. The syntax of a format string is similar to one used by the `printf` family of C functions; some useful extensions are provided as well.

      Format = { character | Specifier }.
      Specifier = "%" Modifier Width
                [ "." Precision [ "." Start ] ] Base.
      Modifier = "+" | "-" | "|" | "0" | "$" | "#".
      Width = [ unsigned number | "*" ].
      Precision = [ unsigned number | "*" ].
      Start = [ unsigned number | "*" ].
      Base = "c" | "d" | "i" | "u" | "o" | "x" | "X" |
             "e" | "f" | "g" |
             "s" | "{}"

The following pairs of symbols starting from the backslash are recognized in `Format` string (but not in strings printed using "`%s`" specifier):

Input | Output
`\n` | the line separator
`\r` | CR (15C)
`\f` | FF (14C)
`\t` | TAB (11C)
`\\` | backslash

`Base` characters and their meanings are listed in the following table:

Base | Argument | Output format
`c` | CHAR | single character
`d`, `i` | integer | signed decimal integer
`u` | integer | unsigned decimal integer
`o` | integer | unsigned octal integer
`X`, `x` | integer | unsigned hexadecimal integer
`E`, `e` | real | floating-point real
`f`, | real | fixed-point real
`G`, `g` | real | either as "f" or "e"
`s` | string | string
`{}` | BITSET | bitset, e.g. `{1,3..5}`

`Modifier` meanings are as follows:

Modifier | Meaning | Default
`"+"` | always print a sign for numbers | only for negative
`"-"` | justify the result to the left | right-justify
`"|"` | center the result |
`"0"` | print leading zeroes for numbers | spaces
`"$"` | the same as "0" |
`"#"` | print a base character ("H" or "B") | no base character
| for "o", "x" and "X" bases only |

`Width` is used to specify the minimum number of characters in the output value. Shorter values are padded with blanks or zeroes to the left and/or to the right, depending on whether a `"-"`, `"|"`, `"0"`, or `"$"` modifier is present. Specifying `Width` never causes longer values to be truncated; if it is not given or is less than the number of characters in the output value, all characters will be output. In some cases, `Precision` may be used for truncation.

If `Width` is set to an asterisk (`"*"`), its actual value will be retrieved from the argument list. It has to be specified before the value being formatted.

`Precision` specifies the number of characters to output or the number of decimal places. Unlike `Width`, it may cause the output value to be truncated or rounded.

If `Precision` is set to an asterisk (`"*"`), its actual value will be taken from the argument list. It has to be specified before the value being formatted, but after the actual value for `Width`, if the latter is also set to "*".

`Precision` value is interpreted depending upon the `Base`, and specifies:

i d u o x X
  The minimum number of digits to output. Shorter values are padded on the left with blanks; longer values are not truncated. Default is 1.
f F e E
  The number of positions after the decimal point. The last digit output is rounded. If `Precision` is 0, decimal point is not printed. Default is 6.
g G
  The maximum number of significant digits to output. By default, all significant digits are printed.
c
  The number of times the character is to output, default is 1.
s
  The maximum number of characters to output. By default, characters are output until `0C` is reached.
{}
  Has no effect.

`Start` may be used with the `"s"` (string) base only and specifies an initial offset in the string being formatted. If `Start` is set to an asterisk (`"*"`), the actual value will be taken from the argument list. It has to be specified before the value being formatted, but after the actual values for `Width` and/or `Precision`, if either of them is also set to "*".

Notes:

- neither the compiler nor the library checks the correctness of actual arguments against format specifications. However, all specifiers, for which no arguments are passed, are ignored, while C `printf`-like functions may produce unpredictable results in such case.
- the ISO conversion library (See String conversions) is used to convert numbers to strings, therefore the results may differ from produced by C functions.

- writeProc - Write Procedure Type
- format - Generic Formatting Procedure
- LineSeparator - Set Line Separator
- TextSeparator - Set Line Separator
- Examples

### writeProc - Write Procedure Type

    TYPE
      writeProc = PROCEDURE(
                    (*handle:*) SYSTEM.ADDRESS,
                    (*string:*) ARRAY OF CHAR,
                    (*length:*) INTEGER
                  );

Module `FormOut`

A procedure of this type is passed to the `format` procedure which uses that procedure to perform output.

### format - Generic Formatting Procedure

    PROCEDURE format(handle : SYSTEM.ADDRESS;
                     write  : writeProc;
                     fmt    : ARRAY OF CHAR;
                     linesep: CHAR;
                     args   : SYSTEM.ADDRESS;
                     size   : CARDINAL);

Module `FormOut`

The `format` procedure forms a string and outputs it via the `write` procedure parameter. The `handle` parameter is passed to the procedure `write` and provides a useful method to pass any information between the caller and the `write` procedure (e.g. output channel or something like it). The (`args`, `size`) pair denotes the address and size of the parameter block. The `linesep` parameter determines the line separator character sequence corresponding to "`\n`". Several standard values of the parameter are defined in the definition module:

`default` | default line separator for binary files
`text` | default line separator for text files
`crlf` | CR LF character sequence

If the `linesep` is not equal to any of the values above, its value will be used as a line separator.

### LineSeparator - Set Line Separator

    PROCEDURE LineSeparator(nl: ARRAY OF CHAR);

Module `FormOut`

Sets the default line separator for binary files. The correct value for the given platform is set in the module initializaion.

### TextSeparator - Set Line Separator

    PROCEDURE TextSeparator(nl: ARRAY OF CHAR);

Module `FormOut`

Sets the default line separator for text files. The correct value for the given platform is set in the module initializaion.

### Examples

The following example shows the implementation of a procedure which produces a format output to an ISO channel.

    PROCEDURE ChanWrite(handle: SYSTEM.ADDRESS;
                        str: ARRAY OF CHAR;
                        len: INTEGER);
      VAR chan: IOChan.ChanId; pos: INTEGER;
    BEGIN
      chan:=SYSTEM.CAST(IOChan.ChanId,handle);
      pos:=0;
      WHILE len > 0 DO
        IF str[pos] = ASCII.LF THEN IOChan.WriteLn
        ELSE IOChan.TextWrite(chan,SYSTEM.ADR(str[pos]),1)
        END;
        INC(pos); DEC(len);
      END;
    END ChanWrite;

    PROCEDURE Print(chan: IOChan.ChanId;
                  format: ARRAY OF CHAR;
                SEQ args: SYSTEM.BYTE);
    BEGIN
      FormOut.format(chan,ChanWrite,format,FormOut.text,
                     SYSTEM.ADR(args),SIZE(args));
    END Print;

The procedure `printf` prints to the standard output channel:

    PROCEDURE printf(f: ARRAY OF CHAR; SEQ x: SYSTEM.BYTE);
    BEGIN
      Print(StdChans.StdOutChan(),f,x);
    END printf;

The procedure `printf` can be used in the conventional for C programmers way, e.g. the call

      printf("%d! = %d\n",5,Factorial(5));

will produce the line Provided that the implementation of the procedure `Factorial` corresponds to its name.

      5! = 120

The `Printf` module implements C-like procedures `printf`, `sprintf`, and `fprintf`.

- Examples:

#### Examples:

Call | Output
`printf("%5.3s","abcdef")` | `abc`
`printf("%-5.3s","abcdef")` | `abc`
`printf("%|5.3s","abcdef")` | `abc`
`printf("%..3s","abcdef")` | `def`
`printf("pos=%3d",13)` | `pos= 13`
`printf("%$3o",13)` | `015`
`printf("%04X",33C)` | `001B`
`printf("%{}",13)` | `{0,2..3}`

## FormStr module

WARNING:

Language extensions are used in the interface of this module.
All your modules importing this one may be non-portable to other compilers.

A string is an array of characters of an arbitrary length. The procedures `print`, `append` and `image` guarantee the presence of the string terminator (`0C`) in the resulting string. See the `FormOut` module overview for the format string syntax.

- print - Print to string
- append - Append to the end of string
- image - Print from the given position
- iscan - Read integer in Modula-2 format

### print - Print to string

    PROCEDURE print(VAR str: ARRAY OF CHAR;
                     format: ARRAY OF CHAR;
                   SEQ args: SYSTEM.BYTE);

Module `FormStr`

Constructs a string specified by the pair (`format`,`args`) and places it into `str`.

### append - Append to the end of string

    PROCEDURE append( VAR str: ARRAY OF CHAR;
                       format: ARRAY OF CHAR;
                     SEQ args: SYSTEM.BYTE);

Module `FormStr`

Appends a string specified by the pair (`format`,`args`) to the end of the string `str`.

### image - Print from the given position

    PROCEDURE image( VAR str: ARRAY OF CHAR;
                     VAR pos: LONGINT;
                      format: ARRAY OF CHAR;
                    SEQ args: SYSTEM.BYTE);

Module `FormStr`

Places a string specified by the pair (`format`,`args`) in the string `str` starting from the position `pos`. After the procedure call, `pos` points to the `0C` or to the position next to the end of the string.

### iscan - Read integer in Modula-2 format

    PROCEDURE iscan( VAR num: INTEGER;
                         str: ARRAY OF CHAR;
                     VAR pos: CARDINAL;
                    VAR done: BOOLEAN);

Module `FormStr`

Reads an integer value from the string `str` starting from the position `pos`. After the procedure call:

`done`
  becomes TRUE, if the attempt was successful;
`pos`
  is the index of the first not scanned character;
`num`
  is the read value when `done=TRUE`.

The number may be represented in any form permitted in Modula-2. In case of an integer overflow `done=FALSE`.

## Printf module

The `Printf` module provides C-like formatted output procedures `fprintf`, `printf`, and `sprintf`,

This module is based on the `FormOut` module and is provided for convenience.

- ChanId - I/O channel identity
- fprintf - Write formatted data to channel
- printf - Print formatted data
- sprintf - Put formatted data to buffer

### ChanId - I/O channel identity

    TYPE ChanId = IOChan.ChanId;

The type `IOChan.ChanId`, which is used in ISO Modula-2 library to identify I/O channels, is reexported.

### fprintf - Write formatted data to channel

    PROCEDURE fprintf(file     : ChanId;
                      format   : ARRAY OF CHAR;
                      SEQ args : SYSTEM.BYTE);

Module `Printf`

The procedure `fprintf` formats and outputs a series of characters and values to the channel identified by `file`. Each argument in `args` is converted and written to `file` according to the corresponding format specification in `format`.

See FormOut module for a description of the format specification and the argument list.

### printf - Print formatted data

    PROCEDURE printf(format   : ARRAY OF CHAR;
                     SEQ args : SYSTEM.BYTE);

Module `Printf`

The procedure `printf` formats and outputs a series of characters and values to the current standard output channel. Each argument in `args` is converted and written to the standard output according to the corresponding format specification in `format`.

See FormOut module for a description of the format specification and the argument list.

### sprintf - Put formatted data to buffer

    PROCEDURE sprintf(VAR buf  : ARRAY OF CHAR;
                      format   : ARRAY OF CHAR;
                      SEQ args : SYSTEM.BYTE);

Module `Printf`

The procedure `sprintf` formats and stores a series of characters and values in the array `buf`. Each argument in `args` is converted and put out according to the corresponding format specification in `format`.

See FormOut module for a description of the format specification and the argument list.

## ProgEnv module

The `ProgEnv` module provides access to the program name, arguments, and environment strings.

- ArgNumber - Return the number of arguments
- GetArg - Get argument
- ArgLength - Return length of argument
- ProgramName - Get program name
- ProgramNameLength - Length of program name
- String - Get environment string
- StringLength - Return environment string length
- Example

### ArgNumber - Return the number of arguments

    PROCEDURE ArgNumber(): CARDINAL;

Module `ProgEnv`

Returns the number of arguments (0 if there is no arguments).

### GetArg - Get argument

    PROCEDURE GetArg(n: CARDINAL; VAR arg: ARRAY OF CHAR);

Module `ProgEnv`

Copies `n`-th argument (`n >= 0`) to `arg`, or empties it if `n >= ArgNumber()`.

### ArgLength - Return length of argument

    PROCEDURE ArgLength(n: CARDINAL): CARDINAL;

Module `ProgEnv`

Returns the length of the `n`-th argument, or 0 if `n>=ArgNumber()`.

### ProgramName - Get program name

    PROCEDURE ProgramName(VAR name: ARRAY OF CHAR);

Module `ProgEnv`

Copies a program name to `name`.

### ProgramNameLength - Length of program name

    PROCEDURE ProgramNameLength(): CARDINAL;

Module `ProgEnv`

Returns the length of the program name.

### String - Get environment string

    PROCEDURE String(name: ARRAY OF CHAR;
                  VAR str: ARRAY OF CHAR);

Module `ProgEnv`

Copies a value of the environment variable `name` to `str` (empty string if the variable is undefined).

### StringLength - Return environment string length

    PROCEDURE StringLength(name: ARRAY OF CHAR): CARDINAL;

Module `ProgEnv`

Returns the length of the environment variable `name` (0 if the variable is undefined).

### Example

The following procedure (in Oberon-2) prints all program arguments:

    PROCEDURE ShowArgs;
      VAR
        str: POINTER TO ARRAY OF CHAR;
        i,args: LONGINT;
    BEGIN
      i:=0;
      args:=ProgEnv.ArgNumber();
      FOR i:=0 TO args-1 DO
        NEW(str,ProgEnv.ArgLength(i)+1);
        ProgEnv.GetArg(i,str^);
        STextIO.WriteString(str^); STextIO.WriteLn;
      END;
    END ShowArgs;

## TimeConv module

The Modula-2 module TimeConv provides operations on values of type `SysClock.DateTime`.

- DateTime - Date and Time Type
- Compare - Compare two clock values
- SubDateDays - Date difference in days
- SubDateSecs - Time difference in seconds
- AddDateDays - Add whole number of days to date
- AddDateSecs - Add seconds to date
- TheDayNumber - Ordinal day number
- TheFractionNumber - Number of fractions passed from midnight
- WeekDay - Determine day of the week
- millisecs - Milliseconds passed from midnight
- time - System time in seconds
- unpack - Unpack system time
- pack - Pack system time
- weekday - Determine day of the week for system time

### DateTime - Date and Time Type

    TYPE DateTime = SysClock.DateTime;

Module `TimeConv`

The `SysClock.DateTime` type is re-exported for convenience.

### Compare - Compare two clock values

    PROCEDURE Compare(dl,dr: DateTime): INTEGER;

Module `TimeConv`

The function procedure `Compare` returns:

- zero, if `dl` represents the same moment as `dr`
- value less than zero, if `dl` is before `dr`
- value greater than zero, if `dl` is after `dr`

Note: If either `dl` or `dr` is invalid, zero is returned.

### SubDateDays - Date difference in days

    PROCEDURE SubDateDays(dl,dr: DateTime): CARDINAL;

Module `TimeConv`

The function procedure `SubDateDays` returns the number of days passed from `dr` to `dl`.

Note: If one of the parameters is invalid or if `dl` is before `dr`, zero is returned.

### SubDateSecs - Time difference in seconds

    PROCEDURE SubDateSecs(dl,dr: DateTime): CARDINAL;

Module `TimeConv`

The function procedure `SubDateSecs` returns the number of seconds passed from `dr` to `dl`.

Note: If one of the parameters is invalid or if `dl` is before `dr`, zero is returned.

### AddDateDays - Add whole number of days to date

    PROCEDURE AddDateDays(d: DateTime;
                          days: CARDINAL;
                          VAR res: DateTime);

Module `TimeConv`

The procedure `AddDateDays` adds `days` days to date `d` and assigns the resulting date to `res`.

Note: If "d" is invalid, "res" is assigned the first valid date.

### AddDateSecs - Add seconds to date

    PROCEDURE AddDateSecs(d: DateTime;
                          secs: CARDINAL;
                          VAR res: DateTime);

Module `TimeConv`

The procedure `AddDateSecs` adds `secs` seconds to date `d` and assigns the resulting date to `res`.

Note: If "d" is invalid, "res" is assigned the first valid date.

### TheDayNumber - Ordinal day number

    PROCEDURE TheDayNumber(d: DateTime): CARDINAL;

Module `TimeConv`

The function procedure `TheDayNumber` returns the ordinal number of the day for the date `d`.

Note: If `d` is invalid, zero is returned.

### TheFractionNumber - Number of fractions passed from midnight

    PROCEDURE TheFractionNumber(d: DateTime): CARDINAL;

Module `TimeConv`

The function procedure `TheFractionNumber` returns the number of fractions passed from time 0:00:00.00 of the day for the date `d`.

Note: If `d` is invalid, zero is returned.

### WeekDay - Determine day of the week

    PROCEDURE WeekDay(d: DateTime): CARDINAL;

Module `TimeConv`

The function procedure `WeekDay` returns day of the week for the date `d`. 0 represents Sunday, 1 - Monday, etc.

Note: If `d` is invalid, zero is returned.

### millisecs - Milliseconds passed from midnight

    PROCEDURE millisecs(): CARDINAL;

Module `TimeConv`

The function procedure `millisecs` returns the number of milliseconds passed from the time 0:00:00.00 of current date as known to the system.

Note: This procedure is system-dependent.

### time - System time in seconds

    PROCEDURE time(): CARDINAL;

Module `TimeConv`

The function procedure `time` returns the number of seconds passed from the time 0:00:00.00 at first valid date for the system.

Note: This procedure is system-dependent.

### unpack - Unpack system time

    PROCEDURE unpack(VAR d: DateTime; secs: CARDINAL);

Module `TimeConv`

The procedure `unpack` assigns to `d` the value corresponding to date/time which is `secs` seconds later than the first valid time/date for the system.

This procedure can be used to examine the first system time/date as follows:

`unpack(firstDateTime,0);`

Note: This procedure is system-dependent.

### pack - Pack system time

    PROCEDURE pack(d: DateTime; VAR secs: CARDINAL);

Module `TimeConv`

The procedure `pack` assigns to `secs` the number of seconds passed from a first valid system date/time to `d`. Its effect is opposite to the `pack` procedure.

Note: This procedure is system-dependent.

### weekday - Determine day of the week for system time

    PROCEDURE weekday(t: CARDINAL): CARDINAL;

Module `TimeConv`

The function procedure `weekday` behaves exactly the same as if it contains the following code:

`unpack(tmpDateTime,t); RETURN WeekDay(tmpDateTime);`

Note: This procedure is system-dependent.

## DStrings module

The module DStrings (written in Oberon-2) defines a dynamic string type and provides some conventional operations.

- String - Dynamic String Type
- Assign - Create and Initialize String
- Append - Append to Dynamic String

### String - Dynamic String Type

    TYPE String* = POINTER TO ARRAY OF CHAR;

Module `DStrings`

### Assign - Create and Initialize String

    PROCEDURE Assign*(s: ARRAY OF CHAR; VAR d: String);

Module `DStrings`

Allocates a new dynamic string and copies string `s` to it. The resulting string always contains a terminator character (0C).

### Append - Append to Dynamic String

    PROCEDURE Append*(s: ARRAY OF CHAR; VAR d: String);

Module `DStrings`

Appends the string `s` to `d`. `d` is extended if necessary. The resulting string always contains the string terminator (0C).

## FilePath module

The `FilePath` module (written in Oberon-2) provides directory search facilities. In the following procedures `path` is a list of directories separated by semicolons, e.g.

      .\SYM;C:\LIB\SYM;C:\XDS\LIB\SYM;.        (Windows)
      ./sym;~/lib/sym;/usr/bin/xds/sym;.       (Unix)

- IsSimpleName - Is just a File Name
- Lookup - Look up File
- UseFirst - Use First Directory

### IsSimpleName - Is just a File Name

    PROCEDURE IsSimpleName*(name: ARRAY OF CHAR): BOOLEAN;

Module `FilePath`

Returns `TRUE`, if `name` contains a file name only (without directories).

### Lookup - Look up File

    PROCEDURE Lookup*(path,name: ARRAY OF CHAR;
                      VAR fname: DStrings.String;
                      VAR n: INTEGER);

Module `FilePath`

Builds a filename using the search path. After a call:

`n = -1` | if `name` is not simple (`fname = name`)
`n = 0` | file is not found (the first directory is used)
`n > 0` | file is found in the `n`-th directory

### UseFirst - Use First Directory

    PROCEDURE UseFirst*(path,name: ARRAY OF CHAR;
                        VAR fname: DStrings.String);

Module `FilePath`

Builds a filename using the first directory from the search path.

## RegComp module

This module (written in Oberon-2) implements a comparison of a string with regular expression.

- Regular expressions
- Examples of regular expressions
- Expr - Regular expression
- Compile - Compile regular expression
- Const - Is constant expression
- Match - Compare string with expression
- Len - Length of substring
- Pos - Position of substring
- Substitute - Substitute substrings

### Regular expressions

A regular expression is a string which may contain certain special symbols:

Sequence | Denotes
`*` | an arbitrary sequence of any characters, possibly empty
| (equivalent to `{\000-\377}` expression)
`?` | any single character
| (equivalent to `[\000-\377]` expression)
`[...]` | one of the listed characters
`{...}` | an arbitrary sequence of the listed characters, possibly empty
`\nnn` | the ASCII character with octal code `nnn`, where n is `[0-7]`
`&` | the logical operation AND
`|` | the logical operation OR
`^` | the logical operation NOT
`(...)` | the priority of operations
`$digit` | subexpression number (see below)

A sequence of the form `a-b` used within either `[]` or `{}` brackets denotes all characters from `a` to `b`.

`$digit` may follow `*`, `?`, `[]`, `{}`, or `()` subexpression. For a string matching a regular expression, it represents the corresponding substring.

If you need to use any special symbol as an ordinary symbol, you should precede it with a backslash (`\`), which suppresses interpretation of the following symbol.

### Examples of regular expressions

`{0-9A-F}` defines set of hexadecimal numbers

`[a-zA-z_]` defines a single small or capital letter or an underscore character.

`(({0-9A-Fa-f})$1|({a-zA-Z_})$2))$3` matches both hexadecimal numbers and Modula-2 identifiers. After a successful match, a program may access the hexadecimal number by the `$1` reference, the identifier by the `$2` reference and either of them by the `$3` reference.

`\\\$\{\}\[\]\*\?` represents the string `\${}[]*?`.

### Expr - Regular expression

    TYPE
      Expr*    = POINTER TO ExprDesc;
      ExprDesc = RECORD END;

Module `RegComp`

### Compile - Compile regular expression

    PROCEDURE Compile*(expr: ARRAY OF CHAR;
                    VAR reg: Expr;
                    VAR res: LONGINT);

Module `RegComp`

Compiles a regular expression to an internal form.

Value of `res` | Meaning
`res`0 | error in position ABS(res)
`res` > 0 | done

### Const - Is constant expression

    PROCEDURE Const*(re: Expr): BOOLEAN;

Module `RegComp`

Returns `TRUE`, if the expression does not contain wildcards.

### Match - Compare string with expression

    PROCEDURE Match*(re: Expr;
                      s: ARRAY OF CHAR;
                    pos: LONGINT): BOOLEAN;

Module `RegComp`

Returns `TRUE`, if the expression matches the string `s` starting from the position `pos`.

### Len - Length of substring

    PROCEDURE Len*(re: Expr; n: INTEGER): LONGINT;

Module `RegComp`

Returns the length of the substring which corresponds to `$n` in the last call of the `Match` procedure with the parameter `re`.

### Pos - Position of substring

    PROCEDURE Pos*(re: Expr; n: INTEGER): LONGINT;

Module `RegComp`

Returns the position of the substring which corresponds to `$n` in the last call of the `Match` procedure with the parameter `re`.

### Substitute - Substitute substrings

    PROCEDURE Substitute*(re: Expr;
                         s,m: ARRAY OF CHAR;
                       VAR d: ARRAY OF CHAR);

Module `RegComp`

The substrings of `s` which matched `re` are substituted instead of `$digit` into `m` and the result string is copied into `d`.

Note: The `Match(re,s,0)` call should be issued and tested for success prior to a call to `Substitute`.

- Example

#### Example

After the following sequence of calls

      Compile("{a-z}$1{0-9}$2",re,res);
      IF Match(re,"abcdef153",0) THEN
        Substitute(re,"abcdef153","tail: $2 head: $1",dest);
      END;

the `dest` string will contain

      "tail: 153 head: abcdef"