Google
 
   
Login
Username:

Password:


Lost Password?

Register now!
Search
Main Menu
top books
Polls
What do you think about php-deluxe.net?
Excellent!
Cool
Hmm..not bad
What the hell is this?
encyclopedia
recommendation
compare webbrowser
Freenet DSL
Who's Online
4 user(s) are online (4 user(s) are browsing encyclopedia)

Members: 0
Guests: 4

more...
browser tip
Unix Befehle
manual of unix befehle
recommendation!
Sponsored
partner

MUMPS

MUMPS (all-caps), or simply M, is a programming language particularly powerful for building and managing large Databases and especially text-based data. The database capability is tightly built into the language and is very easy to use for the programmer since the representation is like a simple multiply subscripted array. These structures, globals in MUMPS terminology, are managed on persistent devices like hard drives. All good implementations of MUMPS use sophisticated techniques for managing, caching, buffering, compression and sorting of persistent data. These are normally intrinsic to the implementation and transparent to the programmer. Portability and standardization has been a historic priority over many iterations in operating systems and hardware over the long history of MUMPS.

MUMPS is different from now-standard programming languages which restrict the programmer from doing anything unusual. Programmers enjoy its clean definitions and compact code. It has always been very efficient to program and test because of the interpreted nature provided what complicated IDEs now do for other languages. This is offset by its speed and flexibility in dealing with tasks that would cause problems under the relational database model. M has been called the best-kept secret in the IT industry . This secrecy is historically because no vendor had a strong vested interest in promoting and marketing MUMPS and the emphasis in the MUMPS community has been applications, not promoting the language.

==History== MUMPS started life as the Massachusetts General Hospital Utility Multi-Programming System, developed in Octo Barnett s animal lab at Massachusetts General Hospital (MGH) in Boston, Massachusetts during 1966 and 1967. The original MUMPS system was built on a spare Digital Equipment Corporation PDP-7.

Octo Barnett and Neil Pappalardo were also involved with MGH s plans for a Hospital Information System, obtained a PDP-9 and began using MUMPS in the admissions cycle and laboratory test reporting. MUMPS is an interpreted language and incorporates a hierarchical database file system to standardize interaction with the data. The origins of MUMPS can be traced from Rand Corporation JOSS through BBN s TELCOMP and STRINGCOMP. The MUMPS team deliberately chose to write the new language with portability in mind. Another feature not widely supported in operating systems of the era was computer multitasking, which was also built into MUMPS itself.

MUMPS was soon ported to a PDP-15 where it lived for some time. Developed on a government grant, MUMPS was required to be released in the public domain (no longer a requirement for grants), and was soon ported to a number of other systems including the popular PDP-8, the Data General Nova and the PDP-11. Word of MUMPS spread mostly through the medical community, and by the early 1970s was in widespread use, often being locally modified for their own needs.

By the early 1970s there were many varied implementations of MUMPS on a range of hardware platforms. The most widespread being Digital Equipment Corporations MUMPS-11 on the PDP-11 and Meditech s MIIS. In 1972 various MUMPS users gathered in order to standardize the now fractured language, creating the MUMPS Users Group and MUMPS Development Committee (MDC). These efforts proved successful; a standard was complete by 1974, and was approved, on September 15, 1977, as ANSI standard, X11.1-1997. At about the same time Digital Equipment Corporation launched DSM-11 (Digital Standard MUMPS) for the PDP-11. This quickly dominated the market and became the reference implementation of the time.

During the early in two variants as DSM for OpenVMS, and as DSM for Ultrix.

This period also saw a lot of activity by the MDC. The second revision of the ANSI standard for MUMPS was (X11.1-1984) was approved on November 15, 1984. On November 11, 1990 the third revision of the ANSI standard (X11.1-1990) was approved. In 1992 this same standard was also adopted as ISO standard 11756-1992. Around this time the use of M as an alternative name was sanctioned. On December 8, 1995 the fourth revision of the standard (X11.1-1995) was approved by ANSI, and by ISO in 1999 as ISO 11756-1999. The MDC finalized a further revision to the standard in 1998 but this has never been presented to ANSI for approval.

By . This was based on their ISM product but with some influences from the other products. The assets of Micronetics Design Corporation were also eventually acquired by InterSystems on June 21, 1998.

Greystone Technology Corporation s GT.M product was sold to Sanchez Computer Associates Inc. (now part of Fidelity National Financial Inc.) in the mid 1990s. On [http://www.sanchez.com/news_2000/nr_001107.asp November 7, 2000] Sanchez made GT.M for Linux available under the GNU Public License license. GT.M continues to be available on VMS and UNIX platforms under a traditional license.

The newest implementation of MUMPS, released in April 2002, is an MSM derivative called M21 from the Real Software Company of Rugby, UK.

==Veterans Administration and Department of Defense==

The Veterans Administration (today known as the United States Department of Veterans Affairs) officially adopted MUMPS as the programming language to be used to implement an integrated laboratory / pharmacy / patient admission, tracking and discharge system in the early 1980s. The original version, the Decentralized Hospital Computer Program (DHCP) was delivered early and under budget! DHCP has been continuously extended in the years since. Most of the source code is available at no cost under the FOIA. However, a major module, IFCAP ( Integrated Funds Distribution, Control Point Activity, Accounting and Procurement ) is not available to the general public (but is to hospitals) because it contains certain validation routines and accounting information that could be used for fraud. In order to implement DHCP the VA also wrote an intermediate layer known as FileMan in MUMPS to act as a database management system.

Today, DHCP is known as Veterans Health Information Systems and Technology Architecture (VistA). The [http://www.hardhats.org Hardhats.org] website is the center for the international community of VistA developers and users and also serves something of the same function for MUMPS generally.

In the late 1980 s the United States Department of Defense decided to implement a next-generation healthcare information system for the active military. The contract was awarded to Science Applications International Corporation, which developed the Composite Health Care System (CHCS). Rather than starting from scratch, SAIC started with DHCP and built on it. At this time, IBM decided to enter the market. Rather than develop its own MUMPS implementation it licensed the Micronetic s implementation. However, despite a lot of hype in the MUMPS community, IBM remained interested mainly in selling hardware.

Nearly the entire VA hospital system in the United States and the Indian Health Service, as well as major parts of the United States Department of Defense CHCS hospital system all still run the system for clinical data tracking.

==Other Industries==

MUMPS also gained a following in the financial sector, in this case due to its much higher performance compared to traditional SQL based systems. Given similar hardware, multidimensional databases like MUMPS are typically about six times faster than SQL for transaction processing, making them ideal for online systems like banking. They also range from as-good to hundreds of times faster on queries, with more complex queries always favoring the multidimensional approach. They are also particularly good at looking up related information in other data stores for free , a task that requires an expensive JOIN operation in SQL systems.

As of 2005 most use of M is either in the form of Caché or GT.M. Caché, in particular is being strongly marketed by InterSystems and is having success in penetrating new markets, such as telecomms, where high performance databases are a critical requirement.

=Description=

M is typically an interpreted language, and shares basic syntax with common 1960s data processing languages, most notable those such as COBOL programming language, however Dr. Kevin O Kane has produced a compiler for it as well. Commands are listed one to a line with whitespace being important, and grouped into procedures (subroutines) in a fashion similar to most structured programming systems. Procedures are simply strings, so they can be easily stored in the underlying datastore, meaning that there is no need for stored procedures as there is in SQL – anything can be stored.

A notable curiosity of MUMPS syntax is that spaces are significant: there are contexts in which a pair of spaces is interpreted differently from a single space. As a result, and unlike most programming languages, spaces cannot be inserted freely for readability, except within comments.

A typical M procedure consists of several blocks , each block separated by a label in the first column. Calling into the procedure with no label results in the entire procedure being run, whereas calling with a label skips to that point. This allows programmers to place interactive commands at the top of the procedure and then label the actual start of the code itself, allowing the procedure to be used both interactively and as a function to be called from other code (look at the GRASS programming language article for an example of an alternate way another language deals with similar issues). It is not possible to define command line macros in M like GRASS, but it is possible to type any line of M code and execute it immediately, including subroutines calls.

One main difference between M and most other languages is that M has only a single data type, the literal string, which it invisibly converts into common data types such as numbers or dates. Automated conversion of this sort is common to many scripting programming languages, but is generally considered a bad thing for most languages because it can all too easily lead to mistakes that are difficult to debug. In the case of M this would be hard to avoid however, as the underlying datastore would grow in complexity if it had to deal with different types. As you might expect, M includes a complete and powerful set of string manipulation commands, grouped into libraries.

The key to the M system is that all variables are automatically multi-dimensional. For instance, this command:

SET A= abc

creates the variable A and sets its value to the string. The same variable can then be used to hold additional information:

SET A(1,2)= def

Will place the string def into slot (1,2). Slots can also be designated with strings:

SET A( first_name )= Bob SET A( last_name )= Dobbs

making the variables useful data stores on their own. Note that this example also demonstrates another feature of M, that assignments into variables do not erase other information already there. This makes it easy to build up a complex variable, using several assignments.

M variables work in a similar fashion as with other programming languages, in that when the program exits, the value will be lost. M comes onto its own with its concept of globals, variables which are automatically and invisibly stored to the datastore. Globals appear as normal variables with the caret character in front of the name. Modifying the earlier example thus:

SET ^A( first_name )= Bob SET ^A( last_name )= Dobbs

will result in a new record being created and inserted in the datastore.

One difference between M and the traditional SQL model of a database is the level of the commands in the language. M is a general purpose language with a datastore, whereas SQL is a language dedicated to database functions. This might sound like a minor distinction, but it is rather important to understand it. For instance, SQL includes a search function:

SELECT * FROM user WHERE first_name like Bob%

returns a list of matching records. M has no equivalent high level command like SELECT, instead the programmer must construct a small routine in order to collect up the matching records returned from its lower-level functions. It should also be noted that M does not include any transaction controls, all changes to globals happen instantly, and there is no logging in the basic system. Nor does M include any sort of user-based security.

For all of these reasons one of the most common M programs is a database management system, providing all of the classic ACID properties on top of a generic M implementation. FileMan is one such example. In the 1990s many of these layers were adapted to supporting SQL, turning most M systems into SQL systems. Although the user might be fooled (to some degree) into seeing the system as a SQL database, the system nevertheless retains the speed advantages of the M datastore (see below).

A side effect of the way M evolved is that the M system includes fairly complete support for multi-tasking, multi-user, multi-machine programming. The former two features are now commonplace on most operating systems, but the later is still not cleanly supported by most systems. To demonstrate the ease of multi-machine support, consider:

SET ^|DENVER|A( first_name )= Bob SET ^|DENVER|A( last_name )= Dobbs

which sets up A as before, but this time on the remote machine called DENVER . M programs are thus trivial to distribute over many machines, a feature that is still difficult on most SQL systems. This support also made it easy to expose the same sorts of distribution in the SQL (and other) layers with ease, and it s not uncommon for M systems to be a better distributed SQL solution than a real SQL system.

Another use of M in more recent times has been to create object databases. By flattening objects into a string representation, like XML, M systems can be used to store objects. An M program then converts back and forth between the real objects and the string representations under it, and is able to do so much faster than similar object-relational mapping systems running over relational databases. This should be expected, if M can be used to make a SQL that s faster than SQL, making an object database that does t require conversion to and from SQL in the middle is bound to be even faster.

=The MUMPS database=

In the traditional relational model, datastores consist of a number of tables, each one holding records for some particular object (or entity ). For instance, an address book application would typically contain tables for PEOPLE, ADDRESSES and PHONE_NUMBERS. The tables consist of a number of fixed-width columns holding one basic piece of data (like first_name ), and each record is a row.

In this example any row in ADDRESSES is for a particular row in PEOPLE. SQL does not understand the concept of ownership however, and requires the user to collect this information back up. SQL supports this through procedure, using the concept of a foreign key ; copying some unique bit of data found in the PEOPLE table into the ADDRESS table.

To re-create a single real record for the address book, the user must instruct the database to collect up the row in PEOPLE they are interested in, extract the key, and then search the ADDRESSES and PHONE_NUMBERS tables for all the rows containing this key.

The SQL syntax for join (SQL)ing tables may seem simpler to some programmers however:

SELECT * from PEOPLE p, ADDRESSES a, PHONE_NUMBERS n WHERE p.id = a.person_id AND p.id = n.person_id AND p.first_name = Bob

In this example the WHERE looks for all the a s and n s (addresses and phone numbers) that have the person s ID tag stored inside them, but only for p s named Bob.

This trivial example already requires three lookups in different tables to return the data, which, as you might expect, is very slow. In order to improve performance, the database administrator will place an index on heavily-searched columns, in this example the person_id columns. An index consists of a column containing the data to be found, and the record number of the matching row in the table. This is the reason that tables are fixed width, so that the database can easily figure out the physical location of the record given the location of the start of the table, the length of any row, and the number of rows to skip. Without this simplification, performance of the relational model would be unusable.

M s datastore stores only the physical locations. This means that records can be of any length, placed anywhere, and contain anything. Searching is not needed to find any record, a pointer directly to that record is easily retrieved and followed to the data in question. The physical data in an M is typically stored in a hierarchical structure of strings, arranged as an ordered tree. This provides another advantage over the relational model, as empty cells do not take up room as they do in the fixed-length relational table. M databases are therefore smaller and more space efficient than relational data structures. The caching methods used allow for multiple users to access the data simultaneously. This means that multiple users in the same data structures will by their use, increase the likelyhood that the data node being sought is actually still in memory. On an operational system that has been running for a while, the cache hit ratio is about 85%, which means that only about 15% of the I/O reads will result in an actual disk access. This is another reason for MUMPS increased performance (less disk operations).

[Sorry, but this whole paragraph is wrong.]{So why doesn t the relational model do the same thing Historical accident. At the time the difference in speed between storage and processor was much smaller than it is today, and the cost of having the CPU follow a pointer was expensive compared to the simple arithmetic needed for an index. Today the CPU s have grown many times faster than the storage, so this cost is effectively zero. This is the main reason why multidimensional datastores outperform relational ones today, something that was not true in the 1970s when the two models were in competition.} (Sorry, but this is not why. MUMPS was faster before and it is even faster now.)

[Please replace the previous paragraph, with this][So why doesn t the relational model do the same thing Actually, some of the larger relational databases actually do relational structures behind the scenes. They got a lot of scalability out of this design change. But they have not been able to provide a logical schema to replace their physical schema. Most of the successful MUMPS-bases data management systems use a highly dynamic ]

M globals are, in fact, indexes. Each node in the global contains a pointer to the data. The actual method of access to the data structure is left to the implementor. The pointer system via the node reference is an abstraction which resolves to a string of data. Unlike the relational model, where indexes are a special-purpose object included as a necessary evil used in some lookups, under MUMPS, the data is accessed in the manner which makes the most sense to the application. The nodes are character and the indexes from the nodes to the actual data are never seen. It is because MUMPS is a logical binding rather than a physical binding that makes the MUMPS data so portable and readable. This is yet another reason for MUMPS s impressive error-time supportability as well as platform independence.

[[Where did this come from It may be correct for a single application, but certainly not the general case.] This makes M systems particularly well suited to looking up related data, as in the example above. The equivalent M statement would be something more akin to:

SELECT * from PEOPLE p, ADDRESSES a, PHONE_NUMBERS n WHERE p.first_name = Bob

Related information can be stored directly in the index, in p.addresses for example. In this case no lookup is needed, PEOPLE can point directly to the addresses and phone numbers. ]

The biggest consequence of this internal representation is that database operations are economical (in both disk space and execution time as well as portability). MUMPS is extremely well suited to real world data, which is often sparse (ie has missing fields). There is no penalty in storage space if a defined data value is not present. This is an extremely helpful feature in a clinical context.

It cannot be overemphasized that real-world applications really do make heavy and unlimited use of these persistent, disk-resident global arrays, which can be of gigabytes in size. This is a notable difference between M and other languages (e.g. Perl) which provide dictionaries, maps, or other string-indexed dynamic arrays which are RAM-resident and hence limited in capacity. The ability to access string-subscripted multi-dimensional arrays, and to freely add and delete new elements, is not a theoretical capability. It is how the MUMPS language is intended to be used. Surviving M implementations are the result of heavy marketplace competition which was largely based on the ability of vendors to provide efficient and robust implementations of these globals.

MUMPS includes almost no operating system specific command syntax, very few file system interface commands, and no machine specific commands. (Idiomatic M applications store data within disk-resident globals; the fact that these globals reside in operating system files is invisible to the application code). It is thus quite portable. Additionally, database manipulation code is extremely brief. A MUMPS routine implementing a complex database interaction might be a page or two of code. The equivalent in a less high level language (C, Pascal, Fortran, ...) is likely to be an order of magnitude larger. Several studies done in the 1980s and 1990s contrasted M rapid applicaton development with other systems including COBOL and SQL based systems. The results, published in the journal M Computing provide support for the claim by M afficionados that M is a highly cost effective application programming tool.

=Summary of key language features=

This incomplete, informal sketch seeks to give programmers familiar with other languages a feeling for what M is like. Neither the language description and the descriptions of each feature are complete, and many significant features have been omitted for brevity. These notes reflect the language circa 1994. ANSI X11.11995 gives a complete, formal description of the language; an annotated version of this standard is [http://207.192.157.194/Demo/AnnoStdFrame=Main&Page=a100002&Edition=1995 available online].

Data types: one universal datatype, interpreted/converted to string, integer, or floating-point number as context requires. Like Visual BASIC variant type.

Booleans: In IF statements and other conditionals, any nonzero value is treated as True. a numeric less than, numeric greater than = string equality [ string contains substring. ABCD [ BC → 1 (true) ] string lexically follows. Z ] A → 1 (true) ]] string sorts after. 1 ]] A → 0 (false) pattern match operator, (regular expression string matching)

Intrinsic (built-in) functions:

Important structural components of the language (not commonly found in other languages):

$DATA(V) tests if a V is defined (has data) or not, and if V is an array or not. $GET(variable) tests value of variable, and if not defined, returns empty string $ORDER, $QUERY traverse arrays in sorted order $ORDER(a( abc )) value v is the next subscript, following abc , according to the M collating sequence, such that a(v) is defined. $PIECE(string,delimiter,position) see above $SELECT(c1:v1,c2:v2,1:v3) if c1 is true yields v1, else if c2 is true yields v2, otherwise yields v3 $STACK(stacklevel) return information in deeper stack levels $TEXT(FOO+3^PGM) returns text of source code at line FOO+3 in routine PGM

Convenience functions similar to library functions in other languages:

$ASCII, $CHAR text-to-ASCII-code and inverse $EXTRACT(string,5,10) characters 5 through 10 of string; may be assignment target $FIND(string,find,from) substring search $FNUMBER() floating point formatting including numeric commas $JUSTIFY() general string formatting with limited numeric $LENGTH(string) returns a count of the number of bytes in string $RANDOM(100) random number in range 0 to 99 inclusive $REVERSE(string) reverse the characters in the string $TRANSLATE( abcd , ab , AB ) character substitution; yields ABcd

Intrinsic (built-in) variables: Intrinic variables

$DEVICE status variable for current device $ESTACK, $ECODE, $ETRAP error handling variables $HOROLOG gives current date and time as day offsets from January 1, 1841 and seconds since midnight. $IO, $PRINCIPAL the current and first I/O device for a job or process $JOB the unique identifier for the current job or process $KEY auxillary status information from previous READ command. $QUIT whether current subroutine was invoked as a function or subroutine. $STACK current depth of subroutine stack $STORAGE current amount of memory available to current job or process $SYSTEM the unique identifier of current system or domain of concurrent processes $TEST success and failure flag for most recent timeout or IF condition evaluation. $TLEVEL current database transaction depth $TRESTART count of restarts that have occurred on current database transaction. $X, $Y current Column and line number on current device

=Relationships between MUMPS, Caché, MIIS, MAGIC, InterSystems and Meditech=

Early development of MUMPS is credited to A. Neil Pappalardo and Octo Barnett of Massachusetts General Hospital.

MUMPS evolution took two major directions: MUMPS proper and MIIS. MUMPS became an ANSI and ISO-standard language, and has been available for nearly two decades from a number of vendors. Gradually, one vendor, InterSystems, came to dominate. The result is that as of 2004 commercial MUMPS is today primarily hidden as the foundation of the InterSystems-proprietary system, Caché . Caché is available for multiple operating systems, including OpenVMS, Sun Microsystems Solaris, Linux, Microsoft Windows, Unix, and Mac OS X under several licenses, including no-cost non-commercial use. InterSystems does not sell applications itself, but supplies Caché and other development tools to companies which use them to build applications.

Independent of InterSystems is the GT.M implementation of MUMPS. It is supported commercially for many platforms such as OpenVMS, Sun Microsystems Solaris, Microsoft Windows, Unix, and Mac OS X with the Linux version for x86 processors open source.

Another line of development was led by Pappalardo, founder of Meditech, a successful vendor of medical applications and complete medical data processing systems. Within Meditech, an early version of MUMPS evolved into a language named MIIS (Meditech Interactive Information System), and a successor named MAGIC (not to be confused with a different PC database product of the same name). In contrast to InterSystems business strategy, MIIS and MAGIC are used only within Meditech and are not marketed to outside application developers.

A GNU/GPL C/C++ based Mumps_compiler is available for Linux, Windows and Windows/Cygwin based systems that translates Mumps to C++. This package also includes a C++ Multidimensional_hierarchical_toolkit class library that provides a Mumps personality and data base access for C++ programs.

= MUMPS vs. M =

While of little interest to outsiders, this topic was and is contentious within the MUMPS/M community.

All of the following opinions can and have been supported by knowledgeable people at various times: *The name became M in 1993 when the M Technology Association adopted it. *The name became M on December 8th, 1995 with the approval of ANSI X11.1-1995 *Both M and MUMPS are officially accepted names. *M is only an alternate name or nickname for the language, and MUMPS is still the official name.

Some of the contention arose in response to strong advocacy for the name M on the part of one particular commercial interest, InterSystems, whose CEO disliked the name MUMPS and felt that it represented a serious marketing obstacle for InterSystems. Thus advocacy for the name M to some extent became identified as alignment with InterSystems. The dispute also reflected rivalry between organizations (the M Technology Association, the MUMPS development committee, the ANSI and ISO standards committee) as to who determines the official name of the language. Some writers have attempted to defuse the issue by referring to the language as M[UMPS], square brackets being the customary notation for optional syntax elements.

Since the M Technology Association dissolved in 2002 and the standards were administratively withdrawn, it can be argued that as of 2004 the language has no official standard and, therefore, no official name.

=The December 31, 1840 epoch=

In M, the current date and time is contained in a special system variable, $H (for HOROLOG ). The format is a pair of integers separated by a comma, e.g. 54321,12345 The first number is the number of days since December 31st, 1840, i.e. day number 1 is January 1st, 1841; the second is the number of seconds since midnight.

The reason for this choice of epoch is a bit of MUMPS trivia that illustrates the degree to which the design of MUMPS was driven by practical considerations. James M. Poitras has written that he chose this epoch for the date and time routines in a package developed by his group at MGH in 1969: I remembered reading of the oldest (one of the oldest) U.S. citizen, a Civil War veteran, who was 121 years old at the time. Since I wanted to be able to represent dates in a Julian-type form so that age could be easily calculated and to be able to represent any birth date in the numeric range selected, I decided that a starting date in the early 1840s would be safe. Since my algorithm worked most logically when every fourth year was a leap year, the first year was taken as 1841. The zero point was then December 31, 1840.... I wasn t party to the MDC negotiations, but I did explain the logic of my choice to members of the Committee.

(More colorful versions have circulated in the folklore, suggesting, for example, that December 30th, 1840 was the exact date of the first entry in the MGH records, but these appear to be legends).

For those who care about such things, $HOROLOG hit 60000 on April 10th, 2005; will be 70000 on August 26th, 2032; 80000 on January 12th, 2060; 90000 on May 30th, 2087; and 100000 on October 16th, 2114.

=References=

*Walters, Richard (1997). M Programming: A Comprehensive Guide. Digital Press. ISBN 1555581676. *Lewkowicz, John. The Complete MUMPS : An Introduction and Reference Manual for the MUMPS Programming Language. ISBN 0131621254 *Kirsten, Wolfgang, et al. (2003) Object-Oriented Application Development Using the Caché Postrelational Database ISBN 3540009604

=External links=

*[http://www.faqs.org/faqs/m-technology-faq/part1/ M Technology and MUMPS Language FAQ] General source; also specific source for the Poitras quote re the origin of the 1840 epoch. *[http://math-cs.cns.uni.edu/~okane/cgi-bin/newpres/m.compiler/compiler/index.cgi/ Open Source (GPL/LGPL), Kevin O Kane Univ Northern Iowa] *[http://www.cs.uni.edu/~okane/source/ISR/isr.html Information Retrieval in Mumps (book)] *[http://www.cs.uni.edu/~okane/source/mdh.html C++ Mumps Toolkit] *[http://www.radix.net/~demoel/mdc/ MDC - MUMPS Development Committee] *[http://www.camta.net Cache & MUMPS Technology Association of UK & Ireland] *[http://Sanchez-GTM.SourceForge.net/ GTM Open Source MUMPS System, free on Linux - Fidelity Investments/Sanchez/GreyStone] *[http://mumps.sourceforge.net/ MUMPS Systems - Source Forge index] *[http://www.mgateway.com/extreme1.doc Globals: a primer for Relational Programmers]