Written by Paul Floyd
XDS is a commercial package which provides an OS/2 Modula-2/Oberon-2 compiler and development environment.
You can download a demonstration version of the environment from the web at
- http://www.xds.ru/xds/ (Russia - usually rather slow)
- http://www.pmi-soft.com/xds/xds.html (USA)
- http://www.modulaware.com/xds/xds.html (Canada)
It is only about 4M. The install uses the IBM Software Installer Package. There are also some extra examples at the website. It isn't sold directly by XDS in the West, but through resellers. XDS recently signed a distribution agreement with Indelible Blue.
OS/2 isn't the only platform supported, there are also versions for 32-bit Windows and Linux, and in addition to the object-code compiler, there is also a version that translates Modula/Oberon to C. In this case, you need to have a C compiler. On OS/2, Watcom C, C Set ++ 2 or VisualAge C++ 3 are supported directly; other C compilers, such as EMX, can also be used, but would require manual setup. XDS-C is also available for Unix workstations (Sun, HP, DEC etc.).
As part of the support for Modula-2, the compiler is compatible with TopSpeed.
Before going into details about using the compiler, and giving some examples, I'll talk a bit about the implementation.
There's a considerable amount of cross-pollination between the two languages in this compiler. Oberon modules can freely link with Modula-2 modules, and both languages have options to use features present in the other. As I'm not too familiar with Modula, I'll only list them:
- Use of Modula types (enumeration, records with variable parts) through import (not declaration).
- Pragmas contained in <* *>
- There is also a set of guidelines for Oberon writers (Oakwood directives) that have mostly, but not entirely, been implemented. The omissions are: input (mouse and keyboard), file i/o and x-y plotting. The other Oakwood directives are implemented: allow underscore in identifiers, numeric extensions, double dash "--" for comments at the end of lines, constant string concatenation with "+", read-only parameters for procedures, variable numbers of procedure parameters (the last parameter being a sequence of bytes) and, lastly, array and record value constructors.
Although the extended features described in 3. above are available, you have to explicitly configure them in your build. Otherwise you will get errors if you try to compile code that includes these features.
The XDS Environment
XDS comes with an Integrated Development Environment (IDE). This allows you to configure a project, edit files, build a project, compile a file, and launch the debugger. The editor is very basic, and I found myself using EPM [no surprise!]. There is also some integration with the IBM OS/2 Toolkit. This allows you to use utilities like the resource editor. There is little in the way of online help in the IDE, but a set of .inf files covers the compiler and the language comprehensively.
Using the compiler from the command line
xc is the name of the compiler. It can take input from a variety of sources (in this order of priority):
- xc.cfg configuration file (default version is in the bin directory where you installed XDS)
- command-line options
- project file
- pragmas in the source code
By default, source code ending with "mod" is compiled as Modula-2, and "ob2" is used as the extension for Oberon-2 files. In the Oberon world, source files typically end with mod. If you want to override this default, you can either specify the -o2+ option or, to do it globally, change the -oberon extension in the xc.cfg file.
The object code can be linked either with the supplied xlink tool, or an OS/2 linker. If you write a PM application with an rc file, you have to generate the res file with rc (shipped with OS/2 and updated in the OS/2 Toolkit from IBM). If you need to use C headers, there is a tool called h2d that will translate them to Oberon def files. You can then import modules from the converted def file. XDC ships with a copy of os2.h (with ALL other #included files inlined) converted to a def file (Modula-2, but that can be simply imported and used within Oberon-2). Coverage of os2.h is not 100%. For instance, quite a lot of the macros in os2.h that map to other functions are not available. For instance, there is the WinInsertLboxItem macro to insert an item into a listbox. The macro expands to a call to WinSendMessage.
In practice, I've found that I needed to do a lot of manual tweaking in order to be able to build a PM application.
The package comes with "xd", a text mode debugger. People that have used CodeView will feel at home. I was quite impressed with it. In addition, if your application crashes, it will write a file called "errinfo.$$$", which has contents like this:
#RTS: unhandled exception #3: invalid location 000005AE 00000001 E:\JUNK\XDSSAMP\RAILWAY.EXE
If you are using the IDE, you can use the "post-mortem execution history" tool, which can show you exactly where in your code the crash occurred.
If you are programming PM, then it is definitely a "C" world. One way around that is to have a set of class libraries. This is fine if you're using VisualAge C++ and have IBM OpenClass, or any one of several other C++ class libraries. But there is no equivalent available for Oberon. So you are faced with the choice of either writing your own modules to implement PM objects, or else writing Oberon virtually as C but with a slightly different syntax. The free use made of pointers in C does not fit well with the more restricted use of them in Oberon.
I found the runtime libraries that come with the product to be generally adequate.
If you compile your application with debug options, you can run the XDS source profiler against your executable. This produces a binary trace file -- your exe file stem with a ".xpt" extension. You can view the contents with the "xpview" PM utility. It doesn't have the sexy graphics that come with the IBM VisualAge C++ 3.0 profiler, but it does go down to source-level profiling. Most profilers I've used only have function-level granularity. The granularity has a limit of 32ms (IBM provides a high-resolution timer driver).
I've written three relatively simple projects to illustrate the use of this compiler. The first is a PM application that converts Euros to and from the 11 currencies in "Euro land". I can't say that this is a good example of the features of Oberon-2, but it does show how you can build a PM application, and the use of imported Modula-2 modules.
The second is a command line application, which demonstrates more of the features of Oberon-2, such as inheritance.
The last is a little number-crunching application to calculate prime numbers. I used this for the profiler example.
None of these examples are big enough to show the usage of separate modules to achieve data hiding.
[Click here to download the samples.zip file -- Ed.]