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

how to use NAM$L_VER when create a file

 
SOLVED
Go to solution
hf.yao
Occasional Advisor

how to use NAM$L_VER when create a file

Hi, I'm using FAB and RAB to create and write a file. after creation now i want to get the file version number.
I read the , seems i have to supply a NAME block.
But don't know what's the type of nameblock should be declared in PASCAL?
Which document descibes all the related type and routines in pascal?
5 REPLIES 5
Steven Schweda
Honored Contributor
Solution

Re: how to use NAM$L_VER when create a file

I don't know what's true in Pascal, but in C
a NAM is declared much as a FAB or RAB is.

If C example code would be helpful, then you
might look at the source for the Info-ZIP Zip
program (version 3.0 or newer). In
[.vms]vms.c, there's a function,
vms_file_version(), which may be pretty close
to what you seek (other than its being in C).

Naturally, the Zip code is more complicated
than you might like, because for ODS5
extended file specifications, you need to use
a (newer) NAML instead of a NAM, and some
things are done differently with a NAML.

Various C macros are defined in [.vms]vms.h,
and are used to try to hide the differences,
but there is some residual mess. (Zip needs
to work on old/VAX systems, where only NAM
exists, so it is more complicated in this
situation than a more future-oriented program
would be.)

> Which document descibes all the related
> type and routines in pascal?

I don't know. Most of the examples I've seen
in the RMS or system service manuals are in C
or Macro 32, with a bit of Fortran thrown in.
There seems to be a small number of FAB-RAB
things under SYS$EXAMPLES, but I didn't see a
NAM anywhere.
Hein van den Heuvel
Honored Contributor

Re: how to use NAM$L_VER when create a file

WHY do you care about the version and not the exact dev/dir and such ?
There may be better ways to solve the core problem (purges? max versions? single version? ) than checking versions.

Anyway, Pascal has a 'user_action' option for the OPEN.
See:
http://h71000.www7.hp.com/doc/82final/6083/6083pro_022.html#index_x_1019

Use that to get control.
First just call a random function and use the debugger to check out how the FAB and NAM block look like, just to get familiar.

It is fully documented in the Pascal Usersguide, chapter 7

http://h71000.www7.hp.com/doc/82final/6140/6140pro_012.html#open_rms_data_struc_sec

There is also an example of a pascal user_action routine. The USER_ACTION function can be written in any language. Pascal itself, but why not C or Macro if you are more comfortable using that.

Your user open has to learn to walk the FAB thru FAB$L_NAM to NAM$L_RSA or NAM$L_VER + NAM$B_VER
Grab and copy to a global variable.

Actually, you may prefer using PAS$FAB to find the FAB address and take it from there, not needing a global variable.

Finally, you may just want to PUNT this and call LIB$FIND_FILE to find yourself back. Yes, a gross and not always correct hack. quick and dirty!

hth,
Hein
Hein van den Heuvel
Honored Contributor

Re: how to use NAM$L_VER when create a file

Going forward on the post-open PAS$FAB thought...
Started with an OpenVMS Wizard example
(Hoff, did you write that, or John R, or perhaps myself? :-)

Anyway, hacked it up to access the Pascal provided NAM block and RSA (Resultant String Array).

I guess it's been to long I coded Pascal, so I brute forced my way some with typecasts. And I couldn't quickly figure out how to dereference a byte array pointer with a [begin..end] style construct perhaps using the string length, but it kinda works anyway.
Enjoy!

and uh... welcome you all to the year 2010 !


Hein.

$ pas PAS_FAB.PAS
$ lin PAS_FAB
$ run PAS_FAB
Enter file name >> login.com
rsa : 45 EISNER$DRA3:[DECUSERVE_USER.HEIN]LOGIN.COM;29
ver : 3 ;29
file creation time is 9-SEP-2009 17:53:35.37
file revision time is 9-SEP-2009 17:53:35.38

$ type PAS_FAB.PAS
[inherit ('sys$library:starlet','sys$library:pascal$lib_routines')]
program get_data_and_time (input,output);

type
str = packed array [1..100] of char;
ptr_str = ^str;
ptr_nam = ^nam$type;
ptr_fab = ^fab$type;

function pas$fab (var f : [unsafe] text) : ptr_fab; extern;

var
stat : integer;
fabp : ptr_fab;
namp : ptr_nam;
xab_dat,xab_rdt : xab$type;
creation_time : varying [23] of char;
revision_time : varying [23] of char;
filename : varying [255] of char;
rsa : ptr_str;
ver : ptr_str;
f : text;

begin
write('Enter file name >> ');
readln(filename);
writeln;

open (file_variable := f, file_name := filename, history := readonly);
fabp := pas$fab (f);

namp := fabp^.fab$l_nam::ptr_nam;
rsa := namp^.nam$l_rsa::ptr_str;
ver := namp^.nam$l_ver::ptr_str;

writeln ('rsa : ', namp^.nam$b_rsl, ' ', rsa^);
writeln ('ver : ', namp^.nam$b_ver, ' ', ver^);

fabp^.fab$l_xab := iaddress(xab_dat);

xab_dat := zero;
xab_dat.xab$b_cod := xab$c_dat;
xab_dat.xab$b_bln := xab$c_datlen;
xab_dat.xab$l_nxt := iaddress(xab_rdt); { chain the two xab'x together }

xab_rdt := zero;
xab_rdt.xab$b_cod := xab$c_rdt;
xab_rdt.xab$b_bln := xab$c_rdtlen; { the xab$l_nxt field will be zero }

stat := $display(%immed fabp);
if not odd(stat) then lib$stop(stat);

stat := $asctim(creation_time.length,creation_time.body,xab_dat.xab$q_cdt);
if not odd (stat) then lib$stop(stat);

writeln('file creation time is ',creation_time);

stat := $asctim(revision_time.length,revision_time.body,xab_rdt.xab$q_rdt);
if not odd (stat) then lib$stop(stat);

writeln('file revision time is ',revision_time);
end.


John Gillings
Honored Contributor

Re: how to use NAM$L_VER when create a file

It sounds like you're doing direct RMS calls from Pascal.

>"using FAB and RAB to create and write
>a file"

>seems i have to supply a NAME block

Yes, that's how RMS works. There are numerous optional attribute blocks which can hang off a FAB. You supply the ones you want, RMS fills them in, if present, on $OPEN or $CREATE. After the file is opened, you can add new structures and call $DISPLAY to have them filled in.

>But don't know what's the type of nameblock
>should be declared in PASCAL?

See NAM$TYPE in module SYS$SHARE:STARLET, similar to FAB$TYPE and RAB$TYPE that you're probably already using.

When you populate your FAB, just chain an empty NAM block onto the FAB at FAB$L_NAM.

Your code will be something like:

VAR
myfab: FAB$TYPE;
mynam: NAM$TYPE;


myfab^.whatever := yourvalue;
myfab^.FAB$L_NAM := IADDRESS(mynam);

stat:=$CREATE(myfab);

After the $CREATE (or $OPEN), the NAM block will be filled in. The version number string will be at address mynam^.NAM$L_VER length mynam^.NAM$B_VER. How you dereference the string depends on how you want to use it, and your preference for handling variable length strings in Pascal. The simplest way is probably to use it to fill in a string descriptor as the source in a call to STR$COPY_DX where the destination string is a VARYING OF CHAR.

>Which document descibes all the related type
>and routines in pascal?

The RMS manuals are intended to be fairly generic and language independent. There are some details in the Pascal documentation. If you want fine detail, try extracting the Pascal code from SYS$SHARE:STARLETPAS.TLB.

Note, these definitions could be considered advisory. You could define the structures yourself, which in some cases might make for nicer Pascal code (ie: avoiding casts and IADDRESS calls), but that leads to possible maintenance issues.

If I've misread your question, and you're mixing native Pascal calls with RMS, I'd suggest avoiding USER_ACTION and using with PAS$FAB, as in Hein's example. (and Hein, short of redefining all the structures, I don't think you can avoid casting).
A crucible of informative mistakes
hf.yao
Occasional Advisor

Re: how to use NAM$L_VER when create a file

Thanks all