FreeM utility suite

Version 0.5.0.4

Library Format Specification

The format of a specification should preferably follow the MDC standard approach for the interface, e.g.

name [result] (param,...)

where

result is optional and has the form :datatype

param has the format [.]name [:[datatype] [ : optional]]

datatype is one of BOOLEAN, COMPLEX, INTEGER, MATRIX, NAME, REAL, STRING

optional is M or O

plus a description of the functionality and any error codes that are appropriate... An example from the standard is:

ABS:REAL(X:REAL,PREC:INTEGER:O)

Routines

Routine %U

Main menu for utilities - Interactive utility.

Routine %Uf

Main menu for File/Device utilities - Interactive utility.

Routine %Ufdir

File directory utility - Interactive utility.

Routine %Uflis

File Lister - Interactive utility.

Routine %Ufxxx

Not callable at the main entry point. Holds miscellaneous file/device related subroutines for the other %U utility routines.

  1. read(device::O, .result::M, length:INTEGER:O, timeout:INTEGER:O)
  2. Reads into result from device (defaults to current one). result must be defined and if non-null then this will be treated as the default value for the field, i.e. returned in the field value if the read encounters a null string.

    If a length is specified then this is the maximum length allowed.

  3. write(device::O, text::O)
  4. Writes text to the specified device (defaults to current one).

  5. select(device::O, params::O)
  6. Prompts for and selects an output device, using params as the device parameters.

  7. open(device::O, type::O, params::O, timeout:INTEGER:O)
  8. Opens device using params with timeout. Valid value for type are - "in", "out", "inout" and "new".

    If the open is unsuccessful and the type is not "in" then a second attempt is made to open the device as a "new" file.

    The first comma piece of the return value, if not a negative error code, is the device number/name to be used in subsequent read/write/close^%Ufxxx calls.

  9. close(device::O)

    Closes device
  10. header(device, type::O, comment::O)

    Writes a two line header to the device. The first one contains type - current date/time, contained in ****s. The second line is comment.
  11. trailer(device, type::O)

    Writes a two line trailer to the device. The first one is null and the second contains type - current date/time, contained in ****s.
  12. rmdir(path)

    Removes host file directory!!!!
  13. mkdir(path)

    Create Host file directory
  14. direx(path)

    Tests if directory exists

Routine %Ug

Main menu for Global utilities - Interactive utility.

Routine %Ugdel

Global Delete - Interactive utility.

  1. go(select)

    Deletes the globals defined in select (same format as used by gsel^%Ugxxx).

Routine %Ugdir

Global directory utility - Interactive utility.

Routine %Ugexp

Global Export - Interactive utility.

Entry points:

  1. export(device::M, work::O, comment::O) is non-interactive. comment is put into the header records on the file, in addition to the current date/time.
  2. go(device::M, work::O, comment::O) is non-interactive (calling routine has to Open/Close device). comment is put into the header records on the file, in addition to the current date/time

Routine %Ugimp

Global Import - Interactive utility. This allows for the user to restore all globals; alternatively to selectively decide to not restore a global or restore it with a different name. ("-" = skip, "*" = restore all remaining globals, "^" = abort import.)

Entry points:

  1. import(device::M, all:BOOLEAN:O) is non-interactive
    Imports globals from the file/device device into the current UCI/namespace. Note: if all is not true then interactive response is required for each global.
  2. go(device::M, all:BOOLEAN:O) is non-interactive (calling routine has to Open/Close device).
    Note: if all is not true then interactive response is required for each global.

Routine %Uglis

Global Lister - Interactive utility.

Routine %Uglis2

Global Lister - Interactive utility. (Alternative version).

Routine %Ugsea

Global Search and Replace - Interactive utility.

  1. go(device::M, work::O, .search:M, .replace::O, subscript:BOOLEAN:O)

    Searchs the globals defined in work (same format as used by gsel^%Ugxxx) replacing any found string in the array search with the corresponding array element in replace. If there is no corresponding entry in replace then no change is made. The old and new nodes are output to device.

    If subscript is true then the subscript values for all nodes are also searched and replaced. This may involve the changing of multiple nodes in one change. Note: If the new subscript is not in the range remaining to be searched then any sub-tree nodes of this node will not have their data portion scanned.

Routine %Ugxxx

Not callable at the main entry point. Holds miscellaneous global related subroutines for the other %U utility routines.

  1. gsel(work)

    Global selector, creating result in work (defaults to normal %U work global)
  2. gseldisp(work)

    Display currently selected globals.
  3. valid (global)

    True if global is a valid global name.
  4. process (work::M, exec1::M, exec2::M)

    Processes the list of global specifications defined in work, executing the string exec1 for each one found and exec2 for each node encountered within the global specification.

Routine %Ur

Main menu for Routine utilities - Interactive utility.

Routine %Urdel

Routine Delete - Interactive utility.

  1. go(select)

    Deletes the routines defined in select (same format as used by rsel^%Urxxx). Any routines which are not deleted are left defined in select.

Routine %Urdir

Routine Directory - Interactive utility.

Routine %Uredi

Routine Editor - Not callable at the main entry point.

d init^%Uredi initialises Editor. This can then be executed by x^%Ue

Routine %Urexp

Routine Export - Interactive Utility.

  1. go(device::M, select::M, comment::O, version::O, separate:BOOLEAN:O)

    Creates/outputs to a file named device the routines defined in select (same format as used by rsel^%Urxxx). comment is put into the header records on the file, in addition to the current date/time. If version is not null then the first line of each routine will have version added to it preceded by "; " (if version doesn't start with punctuation and the line already contains a comment).

    If separate is true then each routine is saved in a separate file - device/routine.m

Routine %Urfir

Routine First Line Lister - Interactive utility.

  1. go(work::M, device::O)

    Lists the first line of routines defined in work (same format as used by rsel^%Urxxx) on to device.

Routine %Urimp

Routine Import - Interactive utility. This allows for the user to restore all routines; alternatively to selectively decide to not restore a routine or restore it with a different name. ("-" = skip, "*" = restore all remaining routines, "^" = abort import.)

Entry points:

  1. import(device::M, all:BOOLEAN:O) is non-interactive
    Imports routines from the file/device device into the current UCI/namespace. Note: if all is not true then interactive response is required for each routine.
  2. go(device::M, all:BOOLEAN:O) is non-interactive (calling routine has to Open/Close device).
    Note: if all is not true then interactive response is required for each routine.

Routine %Urlis

Routine Lister - Interactive utility.

  1. go(work::M, device::O)

    Lists the routines defined in work (same format as used by rsel^%Urxxx) on to device.

Routine %Ursea

Routine Search and Replace - Interactive utility.

  1. go(device::M, work::O, .search:M, .replace::O)

    Searchs the routines defined in work (same format as used by rsel^%Urxxx) replacing any found string in the array search with the corresponding array element in replace. If there is no corresponding entry in replace then no change is made. The old and new lines are output to device.

Routine %Urxxx

Not callable at the main entry point. Holds miscellaneous routine-related subroutines for the other %U utility routines.

  1. rsel (work)

    Routine selector, creating result in work (defaults to normal %U work global)
  2. rseldisp (work)

    Display currently selected routines
  3. save (routine::M, .array::M)

    Saves text defined in array into routine.
  4. delete (routine)

    Deletes routine
  5. exists (routine)

    True if the routine exists.
  6. valid (routine)

    True if routine is a valid routine name.
  7. process (work::M, exec::M)

    Processes the list of routines defined in work, executing the string exec for each one found.

Routine %Uxdat

Returns a formatted date and time. Non-interactive.

^%Uxdat(date:INTEGER:O, .format:INTEGER:O)

date defaults to the current date = $h

format defaults to 0 and has the following possible values

0 returns DD-MMM-CCYY HH:MM
1 returns CCYY-MM-DD HH:MM:SS

  1. date^%Uxdat(date:INTEGER:O, .format:INTEGER:O)
  2. Returns formatted date (defaults to +$h). The format codes are the same as for ^%Uxdat()

  3. time^%Uxdat(time:INTEGER:O, .format:INTEGER:O)

Returns formatted time (defaults to $p($h,",",2)). The format codes are the same as for ^%Uxdat()

Routine %Uxsea

Search and Replace functions - non-interactive utility.

  1. find (old::M, .search:M, type::O)

    Searchs the string old for a string in the array search. The result is true if a match occurs.

    Type can have the following values
    0 - plain string replacement (default value)
    1 - allows ellipsis (...)
  2. search (old::M, .search:M, .replace::O, type::O)

    Searchs the string old replacing any found string in the array search with the corresponding array element in replace. If there is no corresponding entry in replace then no change is made. The default value for type here is 1 (see above).
  3. input (.search::M, .replace::M)

    User input function to set up search and replace arrays.
  4. header (device::M, description::M, .search::M, .replace::O)

    Outputs standard header for search/replace at top of listings. description is the type of search being undertaken, e.g. Global, Routine.

Routine %Uxxxx

Not callable at the main entry point. Holds miscellaneous subroutines for the other %U utility routines.

  1. init()
  2. Initialises %U utility variables

  3. read(prompt::O, .result::M, help::O, length:INTEGER:O, PX:INTEGER:O, PY:INTEGER:O X:INTEGER:O, Y:INTEGER:O, timeout:INTEGER:O)
  4. Reads into result from the current device. prompt is output, subject to any language conversion. result must be defined and if non-null then this will appear between < and > after any prompt string and be treated as the default value for the field, i.e. returned in the field value if the user doesn't enter anything.

    If a length is specified then this is the maximum length allowed, and may be used in any screen handling implemented (using X and Y as the location or PX and PY for the prompt location). If validation is specified then this will be executed prior to returning a result.

    The following conventions are used on user input:

    ? = help (calls help())
    @ = return null string (needed when default is specified)
    ^ = user abort
    ^^ = ^
    ^? = ?
    ^@ = @

  5. readn(prompt::O, .result::M, help::O, length:NUMBER:O, timeout:INTEGER:O)
  6. As for read except that a newline precedes prompt.

  7. readyn(prompt::O, .result::M, help::O)
  8. As for readn except that the result can only be 1/0, corresponding to entering Yes/No.

  9. write(device::O, text::O, X:INTEGER:O, Y:INTEGER:O)
  10. Writes text to the current device at location X,Y.

  11. writen(text::O)
  12. As for write except that a newline precedes text.

  13. writep(device::O, text::O)
  14. As for writen except that text is converted using lprompt().

  15. writef(format::O, text::O)
  16. As for write except that format is treated as a M[UMPS] format string and precedes text.

  17. rerror(text::M)
  18. Displays an error as a result of previous user input, converting text using lprompt() and preceding it with " - ". text starting with a "?" will not be converted.

  19. merror (number:INTEGER:M)

    Displays an error message corresponding to the (negative) %Utility errors below.
  20. error (text::M)
  21. Displays an error message, converting text using lprompt() and preceding it with "Error - ".

  22. help(help::O)

    Displays help text associated with help. help is of the form subject.item, where subject is normally the routine name for %U utilities. If this subject.item does not exist then subject is shortened one character at a time until a match occurs.
  23. lprompt (text::M)
  24. Returns text converted into a prompt in the appropriate user language. All text after a "-" is left unchanged and if the text contains "~" this is changed to " - " and the preceding text is also left unchanged.

  25. upper (text::M)
  26. Returns text with any lower case characters converted into upper case, taking into account language.

  27. lower (text::M)

Returns text with any upper case characters converted into lower case, taking into account language.

MDC Library Routines

As part of the recent development at the MDC the concept of a M[UMPS] library was introduced, accessible from applications by using $%name^library(parameters). This could be implemented in M[UMPS] code or by the implementor in any other way, but was intended to be provided as part of the delivered M[UMPS] environment and optionally tailorable by users.

This library is provided as part of the utility package here, but needs to be accessed slightly differently since the library facility is now yet available in FreeM - by using $$name^%Ullibrary(parameters).

The library MATH is implemented as routine ^%Ulmath.

The libraries STRING and CHARACTER are implemented as a single routine ^%Ulstring.

Definitions of these can be obtained from the MDC or easily seen from the library itself.

Please note that some of these routines may require ssvns which are not currently available with FreeM.

Error numbering

All errors are negative numbers and returned in the format error,function thus allowing for calling programs to determine, if necessary, exactly where the error occurred. All calling programs should test the result of the extrinsic function and if <0 then an error has occured. Non-negative values may be used to indicate, e.g. the number of values returned, etc. Negative values should be unique throughout the utilities. The ones allocated so far are:

-1 User Abort (^ entered in read^%Uxxxx)
-102 routine not deleted in delete^%Urxxx
-103 device/file not available in open^%Ufxxx
-104 trailer invalid in ^%Urimp/^%Ugimp
-105 routine not saved in save^%Urxxx

Known errors (to be fixed)

  1. error^%Uxxxx needs to convert text strings
  2. Opening of Input or Output files in ^%Ufxxx needs to be made FreeM and not Cache format
  3. %Ugsea uses MERGE if subtree subscripts are changed.
  4. %Ugxxx uses ^$GLOBAL for scanning directory
  5. %Urdir has size problems with large directories
  6. %Ufdir missing

Planned Utility Changes

  1. New utilities
    %Ug (com, cop, edi)
    %Ur (cop,com)
    %Uf (com, cop, del, edi, exp, imp, sea)?
    %Ux(hlp - help entry, par - parameter maintenancepro - prompt entry)
    %Uc*, %Uj*, %Uk*, %Ul*, %Un*, %Us*
  2. Provide operating system indication somewhere and change init^%Uxxxx so that it uses $SYSTEM for FreeM
  3. %Ufxxx - device parameter handling plus validation on file names (perhaps)
  4. %Urexp - Allow for different save formats (compatibility mode)
  5. rerror^%Uxxx should interpret error codes
  6. Provide generic hooks for user-programming interaction whenever routine/global saved, possibly also whenever retrievd.
  7. %Urimp - Implement compatibility mode
    + option to list routines in file at start
  8. %Uxdat alternative date formats + make language definition option (Format 0 = override language)
  9. gsel^%Ugxxx to allow for partial selection of globals + validation on subscripts
    + global range
  10. %Ugexp, %Uglis etc use partial global selection
  11. %Ugexp + %Ugimp - compatibility modes
  12. ^%Urxxx rsel to allow for routine range
    + check on routine actually saved probably required
  13. lower/upper^%Uxxxx make language dependent
  14. %Uflis and %Uglis* are very rudimentary!
  15. %Uxsea - regular expression option
  16. Documentation to include examples.
  17. Cross-namespace access

Utility Development Standards

All utilities are named %U*---, where * is the type of utility (c=character, f=file/device, g=global, j=job, k=lock, l=library, n=namespace, r=routine, s=system, x=general) and --- is the name, e.g. dir for directory. All routines which are subsumed within an overall routine will have a 2 digit suffix, e.g. %Ugdir01.

All input and output will, eventually, be handled through common input/output extrinsic functions. This should allow for greater consistency and also easier language independence if so desired. The read/write %Uxxxx extrinsic functions will automatically convert these prompts into the current language setting, pulling information off ^%Uprompt(language, prompt) if it exists.

All exposed entry points should have alpha labels and be called as extrinsic functions. All internal labels should start with a %.

All routines/functions should have no other side-effects/accesses, e.g. other variables or globals, except where defined in the specification. Apart from anything else all internally used variables should be NEWed (preferably at the initial entry point). [Note: Any changes to $T or the naked reference are not considered side-effects here, but should be avoided if possible - extrinsic functions automatically restore $T anyway.]

It would be nice to have a standard usage of variable names, but ...

Standard global names should follow the routine naming standard. A standard work file (normally ^uwork($j)), which can be modified on a per UCI/namespace basis as part of the system configuration is set up when calling the initialisation module. This should be accessed in any utility using subscript indirection, e.g. @%Uwork@(...)

To allow easy modification it would be sensible for all accessing to specifically named globals, i.e. not those whose names are passed as parameters, within functions should be via name indirection in order to make them easier to change if necessary.

 

Jon Diamond - 1999-05-06