Some sections by Keith Shortridge, ks@aaoepp.aao.gov.au.
The DRAMA system is a portable environment designed for writing distributed instrumentation software. It was written by the Anglo Australian Observatory (AAO) computer group. The AAO is the operator of two large optical telescopes located in New South Wales, Australia, although it is not specific to telescope operations.
DRAMA has similarities to the Starlink ADAM environment (Starlink is the U.K. Astronomy Computer Organisation), but is written entirely in C and has been ported to VAX/VMS, various flavours of UNIX (SunOS, Solaris, OSF) and the VxWorks real-time kernel. Ports to other POSIX like systems should be pratical.
Its basic unit is the TASK. A DRAMA Task is normally implemented as a separate process within a multi-process operating system. A Task may send or receive messages of various types.
The most fundamental message type is the "OBEY" message. An associated name specifies the name of an "Action" that the task will perform. The simplest DRAMA task will set up relationships between "Action" names and C routines. It then enters a loop where messages are received and dispatched to the routine that is the current "handler" for that action.
A DRAMA task may have parameters associated with it which may be read or written by other tasks. So we have "GET" and "SET" messages which get and set the value of a named parameter. We also have "MONITOR" messages which allow a task to be notified if the value of a parameter in another task changes. Task parameters may be hierarchical structures of considerable complexity (although they are often simple scalar values) and a DRAMA message may contain such a structure, so this provides a very flexible way of transferring information around a DRAMA system.
User interfaces may be written using X-Windows Xt based widgets (Such as Motif) or using Tcl/Tk.
A typical DRAMA system will use VMS or Unix machines to run user interfaces and CPU intensive operations while VxWorks based VME systems connected via ethernet run the real-time instrumentation. In addition, the real-time components an often be simulated on the VMS or Unix machines for testing purposes.
There is plenty of documentation on DRAMA although we admit it is not always up to date. Try the WWW page
This section deals with questions about DRAMA concepts.
Q. The command "dits_netstart" creates three processes, transmitter, receiver and master. What are these for.
A. The master program does task loading. First transmitter and receiver and then any loading requested by other programs using messages - this allows loading of tasks on remote machines by sending a message to master on that machine.
In communicating with other machines, transmitter and receiver do the jobs their names suggest. It was thought the jobs should be separated to avoid problems with blocking which you can get during network sends and receives. Also, not all systems have the select system call which allows a task to wait on two sources of input. We don't put the networking ability in the indivual tasks themselves since it would have restricted the choice of communication techniques we could have used. In general, the message notification technique used between two tasks on the one machine is the fastest available on the machine.
When I sat down to answer this one I thought I knew exactly why I did this, but as it turns out, it is probably largely historical. At one stage, the script used the newgrp command, which creates a new shell anyway, so it was easier write assuming that. Since that is no longer done, I could use other techniques but I don't think there are any which are portable across both sh and csh compatiable shells.
A. This is necessary to ensure you have somewhere to send responses - error messages for example. Remember that tasks can distributed and some machines involved may have no user interface at all. In addition, multiple user interfaces may be involved in running a task. As a result, there must be some link back to the user interface where the action was invoked.
Our general approach here at the AAO is that an obeyed action will stay active until the thing it has initiated has stopped. For example, if you have an action which moves a filter wheel, the action does not just start the move, but monitors it and only completes when the wheel is in the new position. Hence, there is an action to signal and a user interface for error messages to be sent too.
The biggest problem we strike with this scheme is how to handle asychronous device error messages, particularly from RS232 driven devices. Our approach in general is to have a POLL action. This will be started by the control task or user interface immediately after a task's initialisation has completed and remains active until cancelled by the user interface. The RS232 interrupt handler can then signal the POLL action for unexpected messages. Note that you could either have the POLL action handle all RS232 input or get it or the interrupt handler to signal another action when an expected message arrives.
I should say that both the above approaches are just approaches we have adopted here. DRAMA does not enforce these approaches, although it was clearly written with them in mind. I few minor changes would probably allow you to send a message from an interrupt handler, it's just a case of working out where responses should go.
This section talks you though some of the philosophy of DRAMA.
Q: What makes something a 'DRAMA program
A: Essentially. using the 'Dits' DRAMA library routines to send messages that invoke named 'actions' in other DRAMA programs and/or being able to respond to such messages. The use of DITS routines need not be explicit - a tcl/tk program can use the 'obey' tcl command provided by the Dtcl DRAMA package. while a C program is more likely to call DitsObey() directly, but it comes to the same thing. The way DRAMA is used at AAO, tcl/tk programs are mainly used at the toplevel of a system to provide the user interface. and most programs at lower levels are C programs This means that the tcl/tk programs may invoke 'actions' in other DRAMA tasks. but do not themselves have userwritten 'actions'. At the bottom level of the AAO systems are tasks, mainly connected with controlling specific hardware, that respond to requests that specify named actions that they provide, but which don't themselves invoke actions in other tasks. Then in the middle are tasks that both respond to requests invoking their own actions and which invoke actions in other tasks. You could say that a DRAMA task is one that is aware of the concept of a named 'action', as defined by DRAMA.
Q: OK. so what is a 'named action'?
A: It's something a DRAMA task knows how to do! Forgetting the tcl/tk DRAMA programs for the moment, a 'conventional' DRAMA task, written in C. looks to the outside world like a black box that knows how to perform certain Jobs. Each of these things it knows how to do is given a name - chosen by the designer of the task and in DRAMA terminology each of these 'things' it knows how to do is an 'action'. It's something it can perform. For example, we might have a low level task that controls a spectrograph - something with various filters. gratings. and other mechanisms. This task might have an action called 'CONFIGURE'. Actions have 'arguments' - additional information whose values control the details of an invocation of that action. So the 'CONFIGURE' action might have an argument 'WAVELENGTH' which would be a floating point number giving the central wavelength for which the spectrograph is to be configured. The spectrograph might have a detector (a CCD camera, perhaps) mounted on it. and there might be another DRAMA task that controls this. Such a detector control task might have an action called 'EXPOSE' with an argument called 'EXPOSURE_TIME' giving the exposure time in seconds for the requested exposure. Now imagine a higher level task responsible for coordinating these two tasks. This might have an action 'TAKE_IMAGE' with two arguments. one specifying a central wavelength and one an exposure time. Without actually getting its electronic hands dirty on actual hardware, this higherlevel task could respond to this action by invoking and monitoring the CONFIGURE action in the spectrograph and then invoking the EXPOSE action for the detector once the spectrograph was configures as required. So an action is something with a name and possiblyarguments that a DRAMA task knows how to do. And from the outside a DRAMA task looks like a black box almost completely defined by its actions and their arguments.
Q: This is sounding a little bit object-oriented.
A: Yes. although it's something ADAM tasks were doing long before OO became a buzzword. Nowadays we occasionally emphasise these O-O aspects of the DRAMA design. but it depends on who we're talking to at the time! It does have a lot to do with 'encapsulation'. It also lends itself to a fairly neat 'inheritance' mechanism, but we need to explain more about how actions are implemented first.
Q: Do DRAMA tasks generally have JUst one 'action'?
A: Not the way we write them at AAO. You could do that if you wanted, but usually we have a very large number of named actions supported by each task. We tend to make our tasks relatively large and relatively intelligent; our spectrograph task will embody everything we know about the spectrograph, and will have highlevel actions like 'CONFIGURE' which actually understand the concept off a central wavelength. and lowlevel actions that provide access to all the individual mechanisms in the thing, such as 'MOVE_FILTER'. 'MOVE_GRATING' and so forth.
Q: Does that mean that DRAMA tasks only perform one action at once? Could you have a 'MOVE_FILTER' going on at the same time as a 'MOVE_GRATING' for example? I assume these are controlling mechanical mechanisms that might take some time to move. so it would be nice to be able to overlap them.
A: Yes. you can have overlapping actions. 'Concurrent' actions. if you prefer.
Q: If you start an action by accident - all to easy with systems where you just click on some icon to start something going - do you have to wait for it to finish, or can you cancel it? Or do you have to kill the task?
A: Killing tasks is messy. It leaves too many things in an unknown state. You certainly don't want to do that. You can indeed cancel an action in a DRAMA task. There is a class of DRAMA message that invokes an action. and we call these 'obey' messages. and these are what we've been talking about so far. There is also a 'kick' message, which is used to communicate with an already executing action. The most common use of the 'kick' message. at least at AAO. is to cancel the action in question.
Q: I can see that you might be able to do that with multithreaded tasks, on Solaris, for example, but DRAMA runs on systems like ULTRIX and VMS that don't support multithreading within a single task. How do you make this work?
A: By a process we describe as 'staging'. This is one of the things that can be a bit offputting when you look at DRAMA code. It's only necessary if you want to be able to a) communicate with a currently active action in a task, or b) run concurrent actions in a task. If you write a DRAMA program where you don't want to be able to do either of these then you don't need to 'stage' actions. However. we expect any task with realtime pretensions to be written with all its actions 'staged'. A DRAMA program written in this way has a 'fixed part' which consists of the DRAMA libraries and a main 'loop'. You write an initialisation routine that defines the actions your program handles and associates 'action routines' with each action. Then it passes control back to the main loop which handles all the details of message receipt and decoding. When an 'obey' message is received specifying one of the actions to be invoked. the main loop calls the specified action routine for that action. That routine is supposed to either complete that action 'immediately' (a vague term. in this context) or to complete what it can immediately and return to the main loop.
Q: OK. if gou go back to the main loop 'immediately'. then the program remains responsive and can accept other 'obey' messages. or a 'kick' message to cancel the action you've just started. But how does the action routine get control back?
A: Before it returns to the main loop, it makes calls that set up the conditions under which it is to be invoked again. What these are depends on what it's just done. It may be controlling a mechanism that gets started off doing something and some I/O may complete when it finishes (that's the nice way of handling this, since it's interruptdriven). In that case. it wants to be invoked again when the I/O (which it can specify) is complete. Alternatively, it may have started off something that needs to be polled to see when it completes (nastier' since it involves polling). In this case, it wants to be invoked again after a time that it specifies. Or it may be ready to carry on right now. and is just returning out of politeness (to give the main loop a chance to see if there are any other messages waiting to be processed), in which case it specifies that it would like to be invoked again immediately. Or it may be a higherlevel task waiting for a message from one of the task it's controlling. in which case it wants to be invoked when that message arrives. Once the specified condition obtains. the main loop will activate that action again
Q: What you've described is cooperative multithreading within a process This is the sort of thing you see in Windows. Macintosh programming. even in Xprograms. isn't it?
A: Yes This all looked very odd when it was introduced in ADAM. but now that people are used to windowing systems it looks much more familiar. It's how you run an eventdriven system without necessarily having preemptive multitasking within a process. Even preemptive multithreading or multitasking still has trouble with cancelling operations, howeverm and if an action remains responsive to the outside world while it's executing it can be asked to cancel itself instead of having to just pull the rug out from the executing thread or task.
Q: What if I can't 'stage' an actions. In some cases it may be inconvenient to keep returning to a fixed part of a task. in others it may just be impossible - for instance, if I have to call some very large mathematical subroutine library to fit a multidimensional surface. I don't have and way to get at the code of a standard library to make it run in a 'staging' mode.
A: The two cases are slightly! different. In one, you have control of the code, but for structural reasons you don't want to use the staging mechanism. In the other, you can't even get at the code. However. both are awkward. It all comes down to a question of keeping the task responsive. You want a task to remain responsive normally because you may want to start additional actions in it. or because you may want to cancel the one that's already started. How long you're prepared to have a task go unresponsive is a matter for your overall system design. If you have an action that is going to have to run for a long time and which is hard to write in a staged way (and it isn't always as hard to stage an action as you might think) then it makes sense to put it in a task by itself. so there's no question of wanting to run concurrent actions. However. you may still want to cancel the action.
Q: What's wrong with just killing the task?
A: It's an option, and DRAMA allows you to kill tasks that you've created. However. it tends to be messy. Things get left around. It depends a little on the operating system. VMS is pretty good about cleaning up after deleted tasks. UNIX is less good (semaphores and the like tend to get left in limbo), and systems like VxWorks can be left with memory problems because a deleted process has allocated memory and was deleted before it released it. It's always best if a task cancels itself. We take cancelling very seriously at AAO - we find that if one thing goes wrong in a system, you can often tidy things up automatically if you can just cancel what's going on, tidy up and retry. And any system controlled by a user with a mouse is going to find that they click on the wrong icon all the time. (And then always automatically click on the OK button without thinking. even if you put up a 'please confirm' dialogue!)
Q: So what are the better options?
A: In the case of the subroutine library where you can't access the code. there isn't much you can do other than kill the task. So if you do that you should make sure that task doesn't grab resources that won't be released by the system when it dies. (DRAMA helps a bit here if you load a task using DRAMA. the DRAMA 'master' task will detect the task deletion and will tidy up anything used by DRAMA itself semaphores, and the like - but it can't help much with allocated memory under VxWorks, for example.) In the case where you have access to the code. you do have one good option. You can insert calls at strategic points to a routine that looks ahead in the DRAMA message queue and see if there is any message queued that concerns the present action. If there is, you can usually be sure it's a 'kick' message requesting a cancellation of the action (if you design things properly). and so you can get the routine to bailout at that point. It isn't as neat as a fully staged action. but it does keep the task responsive.
Q: When one of my action handlers is invoked. how do I know whether it's the start of a new action or a reinvocation as part of the 'staging' process?
A: There is a comprehensive set of enquiry routines that let you find out all the details of why a routine is being invoked. One of these (DitsGetSeq()) gives you a sequence number that is set to zero when the action is first invoked and is incremented by one each time the action is staged. However, we tend to make more use of the DRAMA facility that lets you dynamically change the action handler for an action as the action progresses. So the 'main' action handler for an action will be invoked initially, will do the initial set up, and will then call DitsPutObeyHandler() so that the next time the action is invoked when it gets staged a different routine will be called. This lets an action progress through a natural sequence of processing routines instead of having one handler routine that always has to first work out what stage it's got to
Q: Are the arguments to an action Just simple scalar values?
A: They often are in practice, but an action argument is actually a hierarchical selfdefining data structure of essentially unlimited complexity. A simple scalar is Just a simple instance of such a thing! These structures encoded into byte streams using the SDS library, which also provides routines that can probe through such a structure looking to see what's there. This is the 'selfdefining' aspect of these structures - like doing a directory search, you can look at each item at each level of the structure, see if it's a structure itself or a primitive value like a single number. a character string. or an array. and get its type. size and - of course - the data it contains. Since most actions do just use a set of simple scalar values as arguments. there is a set of routines (the ARG package) that package up the SDS calls needed to access these easily. If gou are using more complex structures as your arguments then gou need to use SDS to access them
Q: Just how many arguments does an action have?
A: Ah. there's a bit of confusion in the nomenclature here. Strictly. an action has just one argument, which is an SDS structure. You can call DitsGetArgument() to get an SDS identifier for this structure (a 'handle' to it, if you like) and then use that in SDS or ARG calls to get at the contents of the structure. In the very common case where there this structure has only one level and that level contains just a set of simple scalar values or strings, these are often referred to as the 'arguments' for the action, and these can be accessed easily using the ARG routines. It's convenient to describe an action as having a number of named arguments, and that's the model presented by the ARG routines. However. strictly speaking. this is implemented using a structure that is the single argument to the action. It might be better if DitsGetArgument() were called DitsGetArgumentStructure() to make it clear that this was a single structure that could contain individual arguments or might contain something more complex for those cases where something more complex was needed.
Q: Is a DRAMA task completely specified by its actions and their arguments?
A: No. It may also have task parameters. A task 'parameter' in DRAMA is a named hierarchical selfdescribing data structure implemented using the SDS library. These are associated with the task, are created by the task and are usually maintained by it. It is possible for an outside task to set the value of a parameter of another task, but we tend not to use this facility very much. This is because the setting is handled by the DRAMA fixed part of the task. not by userwritten code. and so no userwritten code is notified that the parameter has been set. (Actually. DRAMA allows you to provide your own parameter system instead of using the standard one. so you could get this effect if you wanted. but there's not much point.) The userwritten part of the task can read the parameter and see that it's changed, but this isn't elegant compared to the alternative of having an action that sets the parameter to the supplied value of the action argument. That has the required effect, but doesn't happen behind the back of the task. There can be applications where setting a parameter from outside can be useful, but parameters are mostly used to allow a task to provide information for other tasks to get. particularly using the 'monitor' facility provided by DRAMA.
Q: What's the 'monitor' facility?
A: A way of letting tasks keep track of what's going on in other tasks with as little explicit coding as possible. Imagine a task that controls some imaging detector. This will keep getting new images from the detector' and a good question is 'what does it do with such an image once it's got it?'. Usually. the system design will want that image to be passed on to some other task, either for display. processing or recording. How do you tell the detector task which task should be sent the new image? You can hardcode the name of the task to receive the image into the detector task, but that's very inflexible. You can have an action in the detector task that tells it which task the image is to be sent to. This is more nicely structured, but requires that the action in question be coded into the detector task, which complicates the task's code, its interfacem, and is something else to document as well. What we tend to do is use parameter 'monitoring'. The detector control task can have a parameter called 'IMAGE', which will be a structure containing, perhaps amongst other things. the newly read image. Another task on the system can make a standard DRAMA call to indicate that it wants to 'monitor' the IMAGE parameter of the detector task. (We talk about a task 'expressing an interest' in a parameter of another task ) When the parameter changes, a copy of it is automatically sent to the task that is monitoring it. (As a message invoking an action whose name is specified in the original 'monitor' request, and with the parameter as the action argument.) The 'monitor' concept is very flexible. and requires very little explicit code in the tasks involved.
Q: But the task 'expressing an interest' needs code to set up the monitoring.
A: Yes, but it's a very simple standard call that it has to make to do so. Also, there's another wrinkle here. A third task can set up the monitoring on its behalf. A higherlevel controlling task can set up parameter monitoring so that, when a parameter in one task changes, another task (not the control task itself) is automatically sent a copy of the parameter. For example. we have a standard image display task that can handle being sent almost any structure that contains a twodimensional data array. When it's sent it, it displays it. We can fire up any detector task that reads from its detector into a parameter' and have a control task set that parameter to be monitored by the image display task. It's all very neat. Our tcl/tk user interfaces usually work by setting up parameter monitoring. When a monitored parameter changes. a tcl procedure is activated and this can update a screen display with the new parameter value. Using this. we can build user interfaces for tasks that need minimal support code in the tasks themselves.
Q: DRAMA tasks have some objectoriented aspects. such as encapsulation. To what extent do they provide inheritance?
A: There is a rather nice 'inheritance' mechanism available in DRAMA, although you have to take a bit of care setting up the things you inherit. It's based on the way that actions are declared in a DRAMA task and the way that action routines are associated with them. There isn't necessarily any one place where all the definitions of the actions supported by a task have to go. The routine DitsPutActionHandlers() defines a set of named actions and associates them with the routines to be associated with them. However, this routine can be called many times, each time adding to the list of actions supported by the task. If any specific named action is specified in more than one callm the later call overrides any earlier ones for this action. You might have a standard set of actions that apply to many tasks. For example. at AAO all tasks have an INITIALISE action. an EXIT action. a SIMULATE_LEVEL action used to define how the task operates when simulating any hardware it may control, a LOG_LEVEL command defining how it logs commands. and so on. The INITIALISE action may need to be subtly different for many tasks, but most of the others are handled the same way in all tasks indeed. we want that to be the case. because having tasks look consistent is a very good thing. You could then have a single call that sets up all these actions and the standard action handlers for them. If a task then wants to handle. say. INITIALISE. in some slightly different wag. it can make a later call to DitsPutActionHandlers() that overrides the standard action handler by specifying a new handler.
Q: But the code for the default handler will still be included in the executable file?
A: Yes. that's true. but it's not a major disadvantage on most machines nowadays. All it costs is memory. and that's not often at a premium in DRAMA systems. And if it is, you don't have to use the standard actions at all. However, it has proven a really good way to get consistent behaviour for all tasks. Every AAO task has a one line call that sets up our standard set of actions, and you then absolutely know that each AAO task will use EXIT to exit (and not QUIT. or FINISH. or whatever) and will either do exactly the standard thing or. if it does something different it's because the programmer really wanted that to happen and has gone to the trouble of overriding it. We have extended this and have a set of 'generic detector' actions that every imaging detector inherits. providing standard routines to handle standard actions like 'EXPOSE' and 'RECORD'. In this case. the details of how gou take an exposure differ so much from detector to detector that the standard EXPOSE action handler has to use callbacks to usersupplied code to do the real work. This is an example of having to be careful when you write stuff you want to be inheritable but it still enforces a standard interface to the task.
Q: What's the relationship between ADAM and DRAMA?
A: ADAM was - and still is - a data acquisition environment used in astronomy that runs on DEC VAXes under the VMS operating system. The original version of ADAM was written for PerkinElmer (now Concurrent) computers, and this is still in use, but ADAM is generally thought of as a VAX data acquisition system. It is also used as a data reduction environment. and in this guise runs on a number of UNIX systems. DRAMA arose out of a discussion at an ADAM workshop on the subject of how ADAM should evolve to meet the changing requirements of astronomical data acquisition, particularly the use of C (ADAM is a Fortranbased system) and the emergence of realtime kernel systems such as VxWorks. So DRAMA evolved from ADAM. and much of the DRAMA design is based on ADAM ideas, in particular! the way actions are 'staged'. However, it is a completely new system. coded in C. targeted from the start at distributed data acquisition systems using a variety of different operating systems and is intended to provide a tight. efficient. realtime environment. DRAMA is a completely new system. although based in part on experience with ADAM.
Q: Does DRAMA use and ADAM code?
A:No. The base DRAMA system doesn't. DRAMA does not require ADAM in any way, nor does it include ADAM code. However. having said that. tasks written using DRAMA. particularly at AAO. will often also make use of libraries that come from ADAM. ADAM, partly as a result of its use as a data reduction environment, is a rich source of generalpurpose subroutine libraries. For example, any AAO DRAMA task that writes a data file for processing by a data reduction system will do so using the HDS library for hierarchical data file access and this is an ADAM library. So DRAMA doesn't use ADAM. but some examples of tasks written using DRAMA will use parts of ADAM as well as using DRAMA. DRAMA tasks can communicate with ADAM tasks using translator tasks - the content of an ADAM message is a subset of the possible content of a DRAMA messagem, and so an ADAM message may be translated into a DRAMA message, and some DRAMA messages ('obey' messages with simple scalar parameters. for example) can be translated into ADAM messages.
This section talks you though some problems which may be struck while building DRAMA programs..
Q. I am getting undefined global variables when linking my DRAMA programs under VMS. In particular, the variables DitsTask, DitsCurrent and DitsActions. These are defined in DitsSystem.h and I appear to be including the right files
A. If the undefined global variables are in mixed case then the problem is almost certinally a compiler incompatibity problems. You will see the problem if you compile DRAMA using the VMS VAXC compiler but try to use VMS DECC to compile the actual program. This is because DECC uses mixed case names my default whilst VAXC does not.This section deals with questions about running DRAMA programs.
Q. I am now able to compile, link, and run the COFFEE program, and I am able to send it commands using the "ditscmd" program. My next step was to run ditscmd and COFFEE on different machines but I've run into trouble. Apparently in order to do this there must be some daemons running on the machines for when I attempt to run
A. After DRAMA is built, you should find in the same directory that drama_source is in, the file
Q. DRAMA used to work but now I get
A. DRAMA programs use semaphores and sometimes shared memory. There is a system wide limit on the number of Semaphores and the amount of shared memory. DRAMA tries very hard to clean up it's resources but since you can't have a real exit handler under Unix, it is not always successful and you eventually run out. The work around is to use the "cleanup" command ($IMP_DEV/cleanup). When run without any arguments, it will delete any DRAMA semaphores (and other resources) it finds belonging to the user who ran it. Note that this causes any existing DRAMA programs to be killed. The various options to cleanup are
We have a tendency to run cleanup occansionally to be sure we are in a known state, but you must be careful as any running program is killed.
The second part to this problem is if you actually run out of semaphores due to wanting to runn more programs then there are semaphores available.
Increasing the number of semaphores is a Unix system configuration operation.
Under Solaris, you add the following lines to "/etc/system"
I think the first one says a user may have up to 30 semaphores while the second allows for 100 semaphores system wide. You need to reboot for the changes to take effect. The default values are somewhat less then this.
For SunOs 4.1.x machines, Modify the file /sys/(arch)/conf/(host) Where arch = result of the command "uname -," and host is the host specific configuration file. Add or modifiy the lines for the items below
You then need to re build and install the kernel and reboot.
This section deals with questions about the DRAMA interface to Tcl/Tk.
This section deals with problems which may be encounted while building DRAMA under Unix.
A. The problem is that you don't have Motif installed in the expected place. Now if you edit the file
It is probably worth having a look at the other HasXxx items in sun.cf. For example - HasTcl, HasTk and HasCPlusPlus may need to be set.
Currently, only one item in DRAMA is dependent on Motif, the XDITSCMD program - a simple user interface.
After making changes to this file, you will have to rerun the build script.
This section deals with problems which may be encounted while building DRAMA under VMS.
A. You are not automatically picking up the VAX C Run time library. This error should not occur in later versions of DRAMA (V0.3 onwards).
You need to setup the following logical name definitions
A. I think that a previous error, while building DRAMAUTIL, is still causing problems. Unfortunately, when MMS encounters an error during a build, it does not delete the thing it was trying to build. As a result, when the previous link command which produced an invalid executable, MMS left there. Then, when you reran MMS, it found the .exe and decided it was up to date. What you need to do is to get rid of any junk. The command