Operating System - OpenVMS
cancel
Showing results for 
Search instead for 
Did you mean: 

LINKing my program with VMS indirect message file

 
SOLVED
Go to solution
Jess Goodman
Esteemed Contributor

LINKing my program with VMS indirect message file

This takes a while to explain, so bear with me.

I wrote some programs and callable routines that can be used instead of VMS supplied utilities for various reasons. Except for my designed differences, I try to make them function as identically as possible to the VMS utility, including error handling.

This means that I need to signal/return VMS facility-specific status values. Usually a status value I need is defined in a VMS supplied include file. Sometimes I have to hard-code the value in my code (no big deal).

When the VMS utility signals or exits with errors the message text associated with the status value is displayed. If this message text is defined in the facility-specific SYS$MESSAGE: file you can not use F$MESSAGE to redisplay the text unless you first use SET MESSAGE to add it to the list of message files your process knows about.

I would like my programs to work the same way for these facility-specific message values. But how do I get my program to display the actual message text instead of "%fac-e-NOMSG," without having to do a SET MESSAGE command before the program is run?

I would prefer to not have to duplicate all the VMS text messages in a private .MSG file and compile it with SET MESSAGE and link in
the resulting .OBJ file. So what is the best way to tell the LINKer about the existing VMS SYS$MESSAGE:.EXE file?

If I just add "SYS$MESSAGE:xxxMSG.EXE /SHARE" to the LINKer /OPTION file then when I run my program I get a "%DCL-W-ACTIMAGE" error unless I first DEFINE xxxMSG as a logical name pointing to the SYS$MESSAGE file, or copy it to SYS$SHARE:.

Usually I can find a VMS .EXE in SYS$SHARE: that was LINKed with the indiret message file I need (for example SYS$SHARE:UTIL$SHARE.EXE csn be used when SYS$MESSAGE:CLIUTLMSG.EXE is needed), but since I don't otherwise need UTIL$SHARE.EXE it seems stupid to LINK it in and have to suffer version dependencies with it.

Here is an an example of what I am talking about:

$ SUBMIT JUNK.COM /LOG=[NOEXIST]JUNK.LOG
%SUBMIT-F-INVLOGFIL, invalid log file specification
-RMS-E-DNF, directory not found

$ MYSUBMIT JUNK.COM /LOG=[NOEXIST]JUNK.LOG
%SUBMIT-F-NOMSG, Message number 00C18324
-RMS-E-DNF, directory not found
$ SET MESSAGE SYS$MESSAGE:CLIUTLMSG.EXE
$ MYSUBMIT JUNK.COM /LOG=[NOEXIST]JUNK.LOG
%SUBMIT-F-INVLOGFIL, invalid log file specification
-RMS-E-DNF, directory not found

I want MYSUBMIT to output %SUBMIT-F-INVLOGFIL, just like SUBMIT does, without doing SET MESSAGE first.

I see from ANALYZE /IMAGE UTIL$SHARE.EXE that CLIUTLMSG.EXE is listed not in the "Shareable Image List" section, but in a "image section descriptor" section as a "indirect message section filename". Is it possible to LINK CLIUTLMSG with my program the same way (without using a shareable image)?
I have one, but it's personal.
1 REPLY
John Gillings
Honored Contributor
Solution

Re: LINKing my program with VMS indirect message file

Jess,

> Is it possible to LINK CLIUTLMSG with my program the same way (without using a shareable image)?

Sorry, Not with the files distributed with OpenVMS.

See the OpenVMS Command Definition, Librarian and Message Utilities Manual for details on how indirect message files work. Their main purpose is to allow things like multi language support.

There are some indirect message files on your system, for example, LIB$MSGDEF is in STARLET.OLB, but the CLI messages aren't provided.

>"%DCL-W-ACTIMAGE" error unless I first DEFINE xxxMSG as a logical name pointing to the SYS$MESSAGE file, or copy it to SYS$SHARE:.

You could get around this by adding SYS$MESSAGE: to the /SYSTEM/EXEC logical name definition of SYS$SHARE:

$ DEFINE/SYSTEM/EXEC SYS$SHARE SYS$SYSROOT:[SYSLIB], SYS$MESSAGE:

Unsupported, of course, but very easy to back out of if you need to prove it's not the cause of something you want to elevate.

Yet another option is to map the message file at run time. An example call:

LIB$FIND_IMAGE_SYMBOL('CLIUTLMSG','NONE',intvar,'SYS$MESSAGE:.EXE')

This is effectively a "SET MESSAGE" command inside your program.

Note however that since there are no global symbols, and LIB$F_I_S signals messages by default, this will signal a warning because "NONE" is not a valid symbol. You'll have to handle that condition :-(

Simplest is to establish LIB$SIG_TO_RET as a condition handler. For example, here's a little MACRO routine MapMsg which you can call once for each message file you want mapped. Just pass the name by descriptor. In your case 'CLIUTLMSG'.

.title mapmsgfile
.psect $data,rd,wrt,noexe
int: .LONG
nosym: .ASCID /NONE/
msgdir:.ASCID /SYS$MESSAGE:.EXE/

.psect $code,rd,nowrt,exe
.entry MapMsg,^m<>
MOVAL G^LIB$SIG_TO_RET,(FP)
PUSHAB msgdir
PUSHAB int
PUSHAB nosym
PUSHAB @4(AP)
CALLS #4,G^LIB$FIND_IMAGE_SYMBOL
RET
.END

A crucible of informative mistakes