Several of my previous articles has used my VMSCALL library to enable a JVM language (Java, Kotlin, Scala, Groovy, Jython or some lesser known) to call VMS native code (Fortran, Pascal, Basic, C etc.).
This article will do a deeper dive.
Expectations of the reader are:
We will see 7 examples:
There are obviously more possible combinations, but those 7 should provide enough to let the reader understand how to handle other cases for arguments.
The examples will use the natural data types for the languages, which mean that the examples will have small variations - Fortran and Basic will be getting fixed length strings by class S descriptor, Pascal will be getting a varying of char by reference and C will be getting a null terminated char array.
The requirements for this to work are:
VMSCALL library is available here.
Architecturally it looks like:
The syntax is:
call("name of shareable exe", "name of function", pass(argwrapper_1).byXxxx().yyyYyy(),
pass(argwrapper_2).byXxxx().yyyYyy(),
...
pass(argwrapper_n).byXxxx().yyyYyy())
where the arg wrappers have the types:
Native type | VMSCALL wrapper |
---|---|
16 bit integer | Word |
32 bit integer | LongWord |
64 bit integer | QuadWord |
fixed length string | CharacterString |
variable length string (Pascal varying of char) |
VariableCharacterString |
null terminated string (C null terminated char array) |
NullTermCharacterString |
any record/struct | Block |
and .byXxxx() is one of:
and .yyyYyy() is one of:
These should look very familiar if one knows VMS calling convention and traditional VMS documentation.
A few examples:
stat = call("myshr", "myfunc1", pass(new Word(1)).byReference().readOnly(), new LongWord(2).byReference().readOnly())
stat = call("myshr", "myfunc2", pass(new CharacterString("XXXXXXXXXX")).byDescriptor().readOnly())
wrapper = new LongWord()
stat = call("myshr", "myfunc3", pass(wrapper).byReference().writeOnly())
lw = wrapper.getValue()
wrapper = new CharacterString(256)
stat = call("myshr", "myfunc4", pass(wrapper).byReference().writeOnly()
cs = wrapper.toString()
Records/structs are done as classes with annotations.
General syntax:
…
@Struct(…)
class ClassName {
@Field(n=0,type=FieldType.xxxx,…)
typename fieldname
@Field(n=1,type=FieldType.xxxx,…)
typename fieldname
…
}
Where the type xxxx is one of: INT1, INT2, INT4, INT8, UINT1, UINT2, UINT4, FP4, FP8, VMSTIME, UNIXTIME, FIXSTR, FIXSTRNULTERM, VARSTR, VARFIXSTR, PACKEDBCD, VAXFP4, VAXFP8.
Examples:
@Struct
class Simple {
@Field(n=0,type=FieldType.INT4)
int iv
@Field(n=1,type=FieldType.FIXSTR,length=8)
String sv
}
@Struct(alignment=Alignment.ALIGN4)
class SomeIntegers {
@Field(n=0,type=FieldType.INT1)
int iv1
@Field(n=1,type=FieldType.INT2)
int iv2
@Field(n=2,type=FieldType.INT4)
int iv3
}
@Struct
class SomeStrings {
@Field(n=0,type=FieldType.FIXSTR,length=8) // Fortran CHARACTER*8
String sv1
@Field(n=1,type=FieldType.FIXSTRNULTERM,length=8) // C char[8]
String s2
@Field(n=2,type=FieldType.VARFIXSTR,length=8) // Pascal varying [8] of char
String sv3
}
All the string filed types also support encoding=”utf-8” if the default of iso-8859-1 is not desired.
A VMSCALL call is relative expensive mostly because of the expensive handling of parameters.
Simple data types are done like:
Records are even more complex:
Is that a problem? Probably not if one avoid doing something stupid!
Example: If you need to make a billion calls of some native function, then if you do a single VMSCALL call and have some native code do the 1 billion iterations calling the native function you will be fine, but if you let your JVM code do the 1 billion iterations each making a VMSCALL call to the native function, then it may be slow.
n.for:
c--
c in integer arguments
c--
integer*4 function nadd(a,b)
integer*4 a,b
integer*4 c
c = a + b
write(*,100) a,b,c
nadd = 1
100 format(1x,'Fortran says : ',i,' + ',i,' = ', i)
end
c--
c in character arguments
c--
integer*4 function nconc(sa,sb)
character*(*) sa,sb
character*1024 sc
sc = sa // sb
write(*,100) sa,sb,trim(sc)
nconc = 1
100 format(1x,'Fortran says : ',a,' + ',a,' = ', a)
end
c--
c in and out integer arguments
c--
integer*4 function naddret(a,b,c)
integer*4 a,b,c
c = a + b
naddret = 1
end
c--
c in and out character arguments
c--
integer*4 function nconcret(sa,sb,sc)
character*(*) sa,sb,sc
sc = sa//sb
nconcret = 1
end
c--
c inout integer argument
c--
integer*4 function nadd1(v)
integer*4 v
v = v + 1
nadd1 = 1
end
c--
c inout character argument
c--
integer*4 function nconcx(s)
character*4 s
s = trim(s) // 'X'
nconcx = 1
end
c--
c inout record argument
c--
integer*4 function nrecmod(r)
structure /myrec/
integer*1 b1
integer*1 b2
integer*2 w
integer*4 lw
integer*8 t
character*8 s
end structure
record /myrec/r
r.b1 = r.b1 + 1
r.b2 = r.b2 + 1
r.w = r.w + 1
r.lw = r.lw + 1
call sys$gettim(%ref(r.t))
r.s = trim(r.s) // 'X'
nrecmod = 1
end
Build:
$ for n
$ link/share=nfshr n + sys$input/opt
SYMBOL_VECTOR=(NADD=PROCEDURE,-
NCONC=PROCEDURE,-
NADDRET=PROCEDURE,-
NCONCRET=PROCEDURE,-
NADD1=PROCEDURE,-
NCONCX=PROCEDURE,-
NRECMOD=PROCEDURE)
$
$ define/nolog nfshr "''f$parse("nfshr.exe")'"
$ exit
JF.java:
import java.io.UnsupportedEncodingException;
import java.text.DateFormat;;
import java.text.SimpleDateFormat;;
import java.util.Date;
import dk.vajhoej.record.FieldType;
import dk.vajhoej.record.RecordException;
import dk.vajhoej.record.Struct;
import dk.vajhoej.record.StructField;
import static dk.vajhoej.vms.call.VMS.*;
public class JF {
//--
// in integer arguments
//--
private static void test1() {
int a = 123;
int b = 456;
int stat = call("nfshr", "NADD", pass(new LongWord(a)).byReference().readOnly(),
pass(new LongWord(b)).byReference().readOnly());
}
//--
// in character arguments
//--
private static void test2() throws UnsupportedEncodingException {
String sa = "ABC";
String sb = "DEF";
int stat = call("nfshr", "NCONC", pass(new CharacterString(sa)).byDescriptor().readOnly(),
pass(new CharacterString(sb)).byDescriptor().readOnly());
}
//--
// in and out integer arguments
//--
private static void test3() {
int a = 123;
int b = 456;
LongWord cwrap = new LongWord();
int stat = call("nfshr", "NADDRET", pass(new LongWord(a)).byReference().readOnly(),
pass(new LongWord(b)).byReference().readOnly(),
pass(cwrap).byReference().writeOnly());
int c = cwrap.getValue();
System.out.printf("Fortran gave : %d + %d = %d\n", a, b, c);
}
//--
// in and out character arguments
//--
private static void test4() throws UnsupportedEncodingException {
String sa = "ABC";
String sb = "DEF";
CharacterString cswrap = new CharacterString(1024);
int stat = call("nfshr", "NCONCRET", pass(new CharacterString(sa)).byDescriptor().readOnly(),
pass(new CharacterString(sb)).byDescriptor().readOnly(),
pass(cswrap).byDescriptor().writeOnly());
String sc = cswrap.toString();
System.out.printf("Fortran gave : %s + %s = %s\n", sa, sb, sc);
}
//--
// inout integer argument
//--
private static void test5() {
int v = 123;
LongWord vwrap = new LongWord(v);
int stat = call("nfshr", "NADD1", pass(vwrap).byReference().readWrite());
v = vwrap.getValue();
System.out.printf("Fortran gave : %d\n", v);
}
//--
// inout character argument
//--
private static void test6() throws UnsupportedEncodingException {
String s = "ABC";
CharacterString swrap = new CharacterString(s, 1024);
int stat = call("nfshr", "NCONCX", pass(swrap).byDescriptor().readWrite());
s = swrap.toString();
System.out.printf("Fortran gave : %s\n", s);
}
//--
// inout record argument
//--
private static DateFormat df = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss");
@Struct
public static class MyRec {
@StructField(n=0, type=FieldType.INT1)
private int b1;
@StructField(n=1, type=FieldType.INT1)
private int b2;
@StructField(n=2, type=FieldType.INT2)
private int w;
@StructField(n=3, type=FieldType.INT4)
private int lw;
@StructField(n=4, type=FieldType.VMSTIME)
private Date t;
@StructField(n=5, type=FieldType.FIXSTR, length=8, pad=true, padchar=' ')
private String s;
public MyRec() {
this(0, 0, 0, 0, null, null);
}
public MyRec(int b1, int b2, int w, int lw, Date t, String s) {
this.b1 = b1;
this.b2 = b2;
this.w = w;
this.lw = lw;
this.t = t;
this.s = s;
}
public int getB1() {
return b1;
}
public void setB1(int b1) {
this.b1 = b1;
}
public int getB2() {
return b2;
}
public void setB2(int b2) {
this.b2 = b2;
}
public int getW() {
return w;
}
public void setW(int w) {
this.w = w;
}
public int getLw() {
return lw;
}
public void setLw(int lw) {
this.lw = lw;
}
public Date getT() {
return t;
}
public void setT(Date t) {
this.t = t;
}
public String getS() {
return s;
}
public void setS(String s) {
this.s = s;
}
@Override
public String toString() {
return String.format("(%d,%d,%d,%d,%s,%s)", b1, b2, w, lw, df.format(t), s);
}
}
@SuppressWarnings("unchecked")
private static void test7() throws RecordException {
MyRec r = new MyRec(1, 2, 3, 123, null, "ABC");
Block rwrap = new Block(r);
int stat = call("nfshr", "NRECMOD", pass(rwrap).byReference().readWrite());
r = (MyRec)rwrap.getObject(MyRec.class);
System.out.printf("Fortran gave : %s\n", r);
}
public static void main(String[] args) throws UnsupportedEncodingException, RecordException {
test1();
test2();
test3();
test4();
test5();
test6();
test7();
}
}
Build and run:
$ javac -cp /vmsjavacallpath/vmscall.jar:/vmsjavacallpath/record.jar JF.java
$ java -cp .:/vmsjavacallpath/vmscall.jar:/vmsjavacallpath/record.jar JF
JF.groovy:
import java.text.*
import java.util.*
import dk.vajhoej.record.*
import static dk.vajhoej.vms.call.VMS.*
//--
// in integer arguments
//--
def test1() {
a = 123
b = 456
stat = call("nfshr", "NADD", pass(new LongWord(a)).byReference().readOnly(),
pass(new LongWord(b)).byReference().readOnly())
}
//--
// in character arguments
//--
def test2() {
sa = "ABC"
sb = "DEF"
stat = call("nfshr", "NCONC", pass(new CharacterString(sa)).byDescriptor().readOnly(),
pass(new CharacterString(sb)).byDescriptor().readOnly())
}
//--
// in and out integer arguments
//--
def test3() {
a = 123
b = 456
cwrap = new LongWord()
stat = call("nfshr", "NADDRET", pass(new LongWord(a)).byReference().readOnly(),
pass(new LongWord(b)).byReference().readOnly(),
pass(cwrap).byReference().writeOnly())
c = cwrap.getValue()
printf("Fortran gave : %d + %d = %d\n", a, b, c)
}
//--
// in and out character arguments
//--
def test4() {
sa = "ABC"
sb = "DEF"
cswrap = new CharacterString(1024)
stat = call("nfshr", "NCONCRET", pass(new CharacterString(sa)).byDescriptor().readOnly(),
pass(new CharacterString(sb)).byDescriptor().readOnly(),
pass(cswrap).byDescriptor().writeOnly())
sc = cswrap.toString()
printf("Fortran gave : %s + %s = %s\n", sa, sb, sc)
}
//--
// inout integer argument
//--
def test5() {
v = 123
vwrap = new LongWord(v)
stat = call("nfshr", "NADD1", pass(vwrap).byReference().readWrite())
v = vwrap.getValue()
printf("Fortran gave : %d\n", v)
}
//--
// inout character argument
//--
def test6() {
s = "ABC"
swrap = new CharacterString(s, 1024)
stat = call("nfshr", "NCONCX", pass(swrap).byDescriptor().readWrite())
s = swrap.toString()
printf("Fortran gave : %s\n", s)
}
//--
// inout record argument
//--
@Struct
class MyRec {
static DateFormat df = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss")
@StructField(n=0, type=FieldType.INT1)
int b1
@StructField(n=1, type=FieldType.INT1)
int b2
@StructField(n=2, type=FieldType.INT2)
int w
@StructField(n=3, type=FieldType.INT4)
int lw
@StructField(n=4, type=FieldType.VMSTIME)
Date t
@StructField(n=5, type=FieldType.FIXSTR, length=8, pad=true, padchar=' ')
String s
@Override
String toString() {
return String.format("(%d,%d,%d,%d,%s,%s)", b1, b2, w, lw, df.format(t), s)
}
}
def test7() {
r = new MyRec(b1: 1, b2: 2, w: 3, lw: 123, t: null, s: "ABC")
rwrap = new Block(r)
stat = call("nfshr", "NRECMOD", pass(rwrap).byReference().readWrite())
r = (MyRec)rwrap.getObject(MyRec.class)
printf("Fortran gave : %s\n", r)
}
test1()
test2()
test3()
test4()
test5()
test6()
test7()
Run:
$ groovy_cp = "/vmsjavacallpath/vmscall.jar:/vmsjavacallpath/record.jar"
$ groovy JF.groovy
n.pas:
[inherit('sys$library:starlet')]
module n(input, output);
type
BYTE = [byte] -128..127;
WORD = [word] -32768..32767;
pstr = varying [1024] of char;
function trim(s : pstr) : pstr;
var
i : integer;
begin
i := length(s);
while (i > 0) and (s[i] = ' ') do i := i - 1;
trim := substr(s, 1, i);
end;
(*--
in integer arguments
--*)
[global]
function nadd(a : integer; b : integer) : integer;
var
c : integer;
begin
c := a + b;
writeln('Pascal says : ', a, ' + ', b, ' = ', c);
nadd := 1;
end;
(*--
in character arguments
--*)
[global]
function nconc(sa : pstr; sb : pstr) : integer;
var
sc : pstr;
begin
sc := sa + sb;
writeln('Pascal says : ', sa, ' + ', sb, ' = ', sc);
nconc := 1;
end;
(*--
in and out integer arguments
--*)
[global]
function naddret(a : integer; b : integer; var c : integer) : integer;
begin
c := a + b;
naddret := 1;
end;
(*--
in and out character arguments
--*)
[global]
function nconcret(sa : pstr; sb : pstr; var sc : pstr) : integer;
begin
sc := sa + sb;
nconcret := 1;
end;
(*--
inout integer argument
--*)
[global]
function nadd1(var v : integer) : integer;
begin
v := v + 1;
nadd1 := 1;
end;
(*--
inout character argument
--*)
[global]
function nconcx(var s : pstr) : integer;
begin
s := trim(s) + 'X';
nconcx := 1;
end;
(*--
inout record argument
--*)
type
myrec = record
b1 : BYTE;
b2 : BYTE;
w : WORD;
lw : integer;
t : integer64;
s : packed array [1..8] of char;
end;
[global]
function nrecmod(var r : myrec) : integer;
begin
r.b1 := r.b1 + 1;
r.b2 := r.b2 + 1;
r.w := r.w + 1;
r.lw := r.lw + 1;
$gettim(r.t);
r.s := trim(r.s) + 'X';
nrecmod := 1;
end;
end.
Build:
$ pas n
$ link/share=npshr n + sys$input/opt
SYMBOL_VECTOR=(NADD=PROCEDURE,-
NCONC=PROCEDURE,-
NADDRET=PROCEDURE,-
NCONCRET=PROCEDURE,-
NADD1=PROCEDURE,-
NCONCX=PROCEDURE,-
NRECMOD=PROCEDURE)
$
$ define/nolog npshr "''f$parse("npshr.exe")'"
$ exit
JP.java:
import java.io.UnsupportedEncodingException;
import java.text.DateFormat;;
import java.text.SimpleDateFormat;;
import java.util.Date;
import dk.vajhoej.record.FieldType;
import dk.vajhoej.record.RecordException;
import dk.vajhoej.record.Struct;
import dk.vajhoej.record.StructField;
import static dk.vajhoej.vms.call.VMS.*;
public class JP {
//--
// in integer arguments
//--
private static void test1() {
int a = 123;
int b = 456;
int stat = call("npshr", "NADD", pass(new LongWord(a)).byReference().readOnly(),
pass(new LongWord(b)).byReference().readOnly());
}
//--
// in character arguments
//--
private static void test2() throws UnsupportedEncodingException {
String sa = "ABC";
String sb = "DEF";
int stat = call("npshr", "NCONC", pass(new VariableCharacterString(sa)).byReference().readOnly(),
pass(new VariableCharacterString(sb)).byReference().readOnly());
}
//--
// in and out integer arguments
//--
private static void test3() {
int a = 123;
int b = 456;
LongWord cwrap = new LongWord();
int stat = call("npshr", "NADDRET", pass(new LongWord(a)).byReference().readOnly(),
pass(new LongWord(b)).byReference().readOnly(),
pass(cwrap).byReference().writeOnly());
int c = cwrap.getValue();
System.out.printf("Pascal gave : %d + %d = %d\n", a, b, c);
}
//--
// in and out character arguments
//--
private static void test4() throws UnsupportedEncodingException {
String sa = "ABC";
String sb = "DEF";
VariableCharacterString cswrap = new VariableCharacterString(1024);
int stat = call("npshr", "NCONCRET", pass(new VariableCharacterString(sa)).byReference().readOnly(),
pass(new VariableCharacterString(sb)).byReference().readOnly(),
pass(cswrap).byReference().writeOnly());
String sc = cswrap.toString();
System.out.printf("Pascal gave : %s + %s = %s\n", sa, sb, sc);
}
//--
// inout integer argument
//--
private static void test5() {
int v = 123;
LongWord vwrap = new LongWord(v);
int stat = call("npshr", "NADD1", pass(vwrap).byReference().readWrite());
v = vwrap.getValue();
System.out.printf("Pascal gave : %d\n", v);
}
//--
// inout character argument
//--
private static void test6() throws UnsupportedEncodingException {
String s = "ABC";
VariableCharacterString swrap = new VariableCharacterString(s, 1024);
int stat = call("npshr", "NCONCX", pass(swrap).byReference().readWrite());
s = swrap.toString();
System.out.printf("Pascal gave : %s\n", s);
}
//--
// inout record argument
//--
private static DateFormat df = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss");
@Struct
public static class MyRec {
@StructField(n=0, type=FieldType.INT1)
private int b1;
@StructField(n=1, type=FieldType.INT1)
private int b2;
@StructField(n=2, type=FieldType.INT2)
private int w;
@StructField(n=3, type=FieldType.INT4)
private int lw;
@StructField(n=4, type=FieldType.VMSTIME)
private Date t;
@StructField(n=5, type=FieldType.FIXSTR, length=8, pad=true, padchar=' ')
private String s;
public MyRec() {
this(0, 0, 0, 0, null, null);
}
public MyRec(int b1, int b2, int w, int lw, Date t, String s) {
this.b1 = b1;
this.b2 = b2;
this.w = w;
this.lw = lw;
this.t = t;
this.s = s;
}
public int getB1() {
return b1;
}
public void setB1(int b1) {
this.b1 = b1;
}
public int getB2() {
return b2;
}
public void setB2(int b2) {
this.b2 = b2;
}
public int getW() {
return w;
}
public void setW(int w) {
this.w = w;
}
public int getLw() {
return lw;
}
public void setLw(int lw) {
this.lw = lw;
}
public Date getT() {
return t;
}
public void setT(Date t) {
this.t = t;
}
public String getS() {
return s;
}
public void setS(String s) {
this.s = s;
}
@Override
public String toString() {
return String.format("(%d,%d,%d,%d,%s,%s)", b1, b2, w, lw, df.format(t), s);
}
}
@SuppressWarnings("unchecked")
private static void test7() throws RecordException {
MyRec r = new MyRec(1, 2, 3, 123, null, "ABC");
Block rwrap = new Block(r);
int stat = call("npshr", "NRECMOD", pass(rwrap).byReference().readWrite());
r = (MyRec)rwrap.getObject(MyRec.class);
System.out.printf("Pascal gave : %s\n", r);
}
public static void main(String[] args) throws UnsupportedEncodingException, RecordException {
test1();
test2();
test3();
test4();
test5();
test6();
test7();
}
}
Build and run:
$ javac -cp /vmsjavacallpath/vmscall.jar:/vmsjavacallpath/record.jar JP.java
$ java -cp .:/vmsjavacallpath/vmscall.jar:/vmsjavacallpath/record.jar JP
JP.groovy:
import java.text.*
import java.util.*
import dk.vajhoej.record.*
import static dk.vajhoej.vms.call.VMS.*
//--
// in integer arguments
//--
def test1() {
a = 123
b = 456
stat = call("npshr", "NADD", pass(new LongWord(a)).byReference().readOnly(),
pass(new LongWord(b)).byReference().readOnly())
}
//--
// in character arguments
//--
def test2() {
sa = "ABC"
sb = "DEF"
stat = call("npshr", "NCONC", pass(new VariableCharacterString(sa)).byReference().readOnly(),
pass(new VariableCharacterString(sb)).byReference().readOnly())
}
//--
// in and out integer arguments
//--
def test3() {
a = 123
b = 456
cwrap = new LongWord()
stat = call("npshr", "NADDRET", pass(new LongWord(a)).byReference().readOnly(),
pass(new LongWord(b)).byReference().readOnly(),
pass(cwrap).byReference().writeOnly())
c = cwrap.getValue()
printf("Pascal gave : %d + %d = %d\n", a, b, c)
}
//--
// in and out character arguments
//--
def test4() {
sa = "ABC"
sb = "DEF"
cswrap = new VariableCharacterString(1024)
stat = call("npshr", "NCONCRET", pass(new VariableCharacterString(sa)).byReference().readOnly(),
pass(new VariableCharacterString(sb)).byReference().readOnly(),
pass(cswrap).byReference().writeOnly())
sc = cswrap.toString()
printf("Pascal gave : %s + %s = %s\n", sa, sb, sc)
}
//--
// inout integer argument
//--
def test5() {
v = 123
vwrap = new LongWord(v)
stat = call("npshr", "NADD1", pass(vwrap).byReference().readWrite())
v = vwrap.getValue()
printf("Pascal gave : %d\n", v)
}
//--
// inout character argument
//--
def test6() {
s = "ABC"
swrap = new VariableCharacterString(s, 1024)
stat = call("npshr", "NCONCX", pass(swrap).byReference().readWrite())
s = swrap.toString()
printf("Pascal gave : %s\n", s)
}
//--
// inout record argument
//--
@Struct
class MyRec {
static DateFormat df = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss")
@StructField(n=0, type=FieldType.INT1)
int b1
@StructField(n=1, type=FieldType.INT1)
int b2
@StructField(n=2, type=FieldType.INT2)
int w
@StructField(n=3, type=FieldType.INT4)
int lw
@StructField(n=4, type=FieldType.VMSTIME)
Date t
@StructField(n=5, type=FieldType.FIXSTR, length=8, pad=true, padchar=' ')
String s
@Override
String toString() {
return String.format("(%d,%d,%d,%d,%s,%s)", b1, b2, w, lw, df.format(t), s)
}
}
def test7() {
r = new MyRec(b1: 1, b2: 2, w: 3, lw: 123, t: null, s: "ABC")
rwrap = new Block(r)
stat = call("npshr", "NRECMOD", pass(rwrap).byReference().readWrite())
r = (MyRec)rwrap.getObject(MyRec.class)
printf("Pascal gave : %s\n", r)
}
test1()
test2()
test3()
test4()
test5()
test6()
test7()
jp.com:
$ groovy_cp = "/vmsjavacallpath/vmscall.jar:/vmsjavacallpath/record.jar"
$ groovy JP.groovy
n.bas:
!--
! in integer arguments
!--
function integer nadd(integer a, integer b)
declare integer c
c = a + b
print "Basic says : ", a, " + ", b, " = ", c
nadd = 1
end function
!--
! in character arguments
!--
function integer nconc(string sa, string sb)
declare string sc
sc = sa + sb
print "Basic says : ", sa, " + ", sb, " = ", sc
nconc = 1
end function
!--
! in and out integer arguments
!--
function integer naddret(integer a, integer b, integer c)
c = a + b
naddret = 1
end function
!--
! in and out character arguments
!--
function integer nconcret(string sa, string sb, string sc)
sc = sa + sb
nconcret = 1
end function
!--
! inout integer argument
!--
function integer nadd1(integer v)
v = v + 1
nadd1 = 1
end function
!--
! inout character argument
!--
function integer nconcx(string s)
external string function trim(string)
s = trim(s) + "X"
nconcx = 1
end function
!--
! inout record argument
!--
function integer nrecmod(myrec r)
record myrec
byte b1
byte b2
word w
long lw
quad t
string s = 8
end record
external string function trim(string)
external sub sys$gettim(quad)
r::b1 = r::b1 + 1
r::b2 = r::b2 + 1
r::w = r::w + 1
r::lw = r::lw + 1
call sys$gettim(r::t)
r::s = trim(r::s) + "X"
nrecmod = 1
end function
!
function string trim(string s)
declare integer ix
ix = len(s)
while ix > 1 and mid$(s, ix, 1) = " "
ix = ix - 1
next
trim = mid$(s, 1, ix)
end function
Build:
$ bas n
$ link/share=nbshr n + sys$input/opt
SYMBOL_VECTOR=(NADD=PROCEDURE,-
NCONC=PROCEDURE,-
NADDRET=PROCEDURE,-
NCONCRET=PROCEDURE,-
NADD1=PROCEDURE,-
NCONCX=PROCEDURE,-
NRECMOD=PROCEDURE)
$
$ define/nolog nbshr "''f$parse("nbshr.exe")'"
$ exit
JB.java:
import java.io.UnsupportedEncodingException;
import java.text.DateFormat;;
import java.text.SimpleDateFormat;;
import java.util.Date;
import dk.vajhoej.record.FieldType;
import dk.vajhoej.record.RecordException;
import dk.vajhoej.record.Struct;
import dk.vajhoej.record.StructField;
import static dk.vajhoej.vms.call.VMS.*;
public class JB {
//--
// in integer arguments
//--
private static void test1() {
int a = 123;
int b = 456;
int stat = call("nbshr", "NADD", pass(new LongWord(a)).byReference().readOnly(),
pass(new LongWord(b)).byReference().readOnly());
}
//--
// in character arguments
//--
private static void test2() throws UnsupportedEncodingException {
String sa = "ABC";
String sb = "DEF";
int stat = call("nbshr", "NCONC", pass(new CharacterString(sa)).byDescriptor().readOnly(),
pass(new CharacterString(sb)).byDescriptor().readOnly());
}
//--
// in and out integer arguments
//--
private static void test3() {
int a = 123;
int b = 456;
LongWord cwrap = new LongWord();
int stat = call("nbshr", "NADDRET", pass(new LongWord(a)).byReference().readOnly(),
pass(new LongWord(b)).byReference().readOnly(),
pass(cwrap).byReference().writeOnly());
int c = cwrap.getValue();
System.out.printf("Basic gave : %d + %d = %d\n", a, b, c);
}
//--
// in and out character arguments
//--
private static void test4() throws UnsupportedEncodingException {
String sa = "ABC";
String sb = "DEF";
CharacterString cswrap = new CharacterString(1024);
int stat = call("nbshr", "NCONCRET", pass(new CharacterString(sa)).byDescriptor().readOnly(),
pass(new CharacterString(sb)).byDescriptor().readOnly(),
pass(cswrap).byDescriptor().writeOnly());
String sc = cswrap.toString();
System.out.printf("Basic gave : %s + %s = %s\n", sa, sb, sc);
}
//--
// inout integer argument
//--
private static void test5() {
int v = 123;
LongWord vwrap = new LongWord(v);
int stat = call("nbshr", "NADD1", pass(vwrap).byReference().readWrite());
v = vwrap.getValue();
System.out.printf("Basic gave : %d\n", v);
}
//--
// inout character argument
//--
private static void test6() throws UnsupportedEncodingException {
String s = "ABC";
CharacterString swrap = new CharacterString(s, 1024);
int stat = call("nbshr", "NCONCX", pass(swrap).byDescriptor().readWrite());
s = swrap.toString();
System.out.printf("Basic gave : %s\n", s);
}
//--
// inout record argument
//--
private static DateFormat df = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss");
@Struct
public static class MyRec {
@StructField(n=0, type=FieldType.INT1)
private int b1;
@StructField(n=1, type=FieldType.INT1)
private int b2;
@StructField(n=2, type=FieldType.INT2)
private int w;
@StructField(n=3, type=FieldType.INT4)
private int lw;
@StructField(n=4, type=FieldType.VMSTIME)
private Date t;
@StructField(n=5, type=FieldType.FIXSTR, length=8, pad=true, padchar=' ')
private String s;
public MyRec() {
this(0, 0, 0, 0, null, null);
}
public MyRec(int b1, int b2, int w, int lw, Date t, String s) {
this.b1 = b1;
this.b2 = b2;
this.w = w;
this.lw = lw;
this.t = t;
this.s = s;
}
public int getB1() {
return b1;
}
public void setB1(int b1) {
this.b1 = b1;
}
public int getB2() {
return b2;
}
public void setB2(int b2) {
this.b2 = b2;
}
public int getW() {
return w;
}
public void setW(int w) {
this.w = w;
}
public int getLw() {
return lw;
}
public void setLw(int lw) {
this.lw = lw;
}
public Date getT() {
return t;
}
public void setT(Date t) {
this.t = t;
}
public String getS() {
return s;
}
public void setS(String s) {
this.s = s;
}
@Override
public String toString() {
return String.format("(%d,%d,%d,%d,%s,%s)", b1, b2, w, lw, df.format(t), s);
}
}
@SuppressWarnings("unchecked")
private static void test7() throws RecordException {
MyRec r = new MyRec(1, 2, 3, 123, null, "ABC");
Block rwrap = new Block(r);
int stat = call("nbshr", "NRECMOD", pass(rwrap).byReference().readWrite());
r = (MyRec)rwrap.getObject(MyRec.class);
System.out.printf("Basic gave : %s\n", r);
}
public static void main(String[] args) throws UnsupportedEncodingException, RecordException {
test1();
test2();
test3();
test4();
test5();
test6();
test7();
}
}
Build and run:
$ javac -cp /vmsjavacallpath/vmscall.jar:/vmsjavacallpath/record.jar JB.java
$ java -cp .:/vmsjavacallpath/vmscall.jar:/vmsjavacallpath/record.jar JB
JB.groovy:
import java.text.*
import java.util.*
import dk.vajhoej.record.*
import static dk.vajhoej.vms.call.VMS.*
//--
// in integer arguments
//--
def test1() {
a = 123
b = 456
stat = call("nbshr", "NADD", pass(new LongWord(a)).byReference().readOnly(),
pass(new LongWord(b)).byReference().readOnly())
}
//--
// in character arguments
//--
def test2() {
sa = "ABC"
sb = "DEF"
stat = call("nbshr", "NCONC", pass(new CharacterString(sa)).byDescriptor().readOnly(),
pass(new CharacterString(sb)).byDescriptor().readOnly())
}
//--
// in and out integer arguments
//--
def test3() {
a = 123
b = 456
cwrap = new LongWord()
stat = call("nbshr", "NADDRET", pass(new LongWord(a)).byReference().readOnly(),
pass(new LongWord(b)).byReference().readOnly(),
pass(cwrap).byReference().writeOnly())
c = cwrap.getValue()
printf("Basic gave : %d + %d = %d\n", a, b, c)
}
//--
// in and out character arguments
//--
def test4() {
sa = "ABC"
sb = "DEF"
cswrap = new CharacterString(1024)
stat = call("nbshr", "NCONCRET", pass(new CharacterString(sa)).byDescriptor().readOnly(),
pass(new CharacterString(sb)).byDescriptor().readOnly(),
pass(cswrap).byDescriptor().writeOnly())
sc = cswrap.toString()
printf("Basic gave : %s + %s = %s\n", sa, sb, sc)
}
//--
// inout integer argument
//--
def test5() {
v = 123
vwrap = new LongWord(v)
stat = call("nbshr", "NADD1", pass(vwrap).byReference().readWrite())
v = vwrap.getValue()
printf("Basic gave : %d\n", v)
}
//--
// inout character argument
//--
def test6() {
s = "ABC"
swrap = new CharacterString(s, 1024)
stat = call("nbshr", "NCONCX", pass(swrap).byDescriptor().readWrite())
s = swrap.toString()
printf("Basic gave : %s\n", s)
}
//--
// inout record argument
//--
@Struct
class MyRec {
static DateFormat df = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss")
@StructField(n=0, type=FieldType.INT1)
int b1
@StructField(n=1, type=FieldType.INT1)
int b2
@StructField(n=2, type=FieldType.INT2)
int w
@StructField(n=3, type=FieldType.INT4)
int lw
@StructField(n=4, type=FieldType.VMSTIME)
Date t
@StructField(n=5, type=FieldType.FIXSTR, length=8, pad=true, padchar=' ')
String s
@Override
String toString() {
return String.format("(%d,%d,%d,%d,%s,%s)", b1, b2, w, lw, df.format(t), s)
}
}
def test7() {
r = new MyRec(b1: 1, b2: 2, w: 3, lw: 123, t: null, s: "ABC")
rwrap = new Block(r)
stat = call("nbshr", "NRECMOD", pass(rwrap).byReference().readWrite())
r = (MyRec)rwrap.getObject(MyRec.class)
printf("Basic gave : %s\n", r)
}
test1()
test2()
test3()
test4()
test5()
test6()
test7()
Run:
$ groovy_cp = "/vmsjavacallpath/vmscall.jar:/vmsjavacallpath/record.jar"
$ groovy JB.groovy
n.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
//--
// in integer arguments
//--
int nadd(int a, int b)
{
int c = a + b;
printf("C says : %d + %d = %d\n", a, b, c);
return 1;
}
//--
// in character arguments
//--
int nconc(char *sa, char *sb)
{
char *sc = malloc(strlen(sa) + strlen(sb) + 1);
strcpy(sc, sa);
strcat(sc, sb);
printf("C says : %s + %s = %s\n", sa, sb, sc);
free(sc);
return 1;
}
//--
// in and out integer arguments
//--
int naddret(int a, int b, int *c)
{
*c = a + b;
return 1;
}
//--
// in and out character arguments
//--
int nconcret(char *sa, char *sb, char *sc)
{
strcpy(sc, sa);
strcat(sc, sa);
return 1;
}
//--
// inout integer argument
//--
int nadd1(int *v)
{
*v = *v + 1;
return 1;
}
//--
// inout character argument
//--
int nconcx(char *s)
{
char *p = s + strlen(s) - 1;
while(*p == ' ')
{
*p = 0;
p--;
}
strcat(s, "X");
return 1;
}
//--
// inout record argument
//--
struct myrec
{
char b1;
char b2;
short w;
int lw;
time_t t;
char s[8];
};
int nrecmod(struct myrec *r)
{
r->b1++;
r->b2++;
r->w++;
r->lw++;
r->t = time(NULL);
strcat(r->s, "X");
return 1;
}
Build and run:
$ cc n
$ link/share=ncshr n + sys$input/opt
SYMBOL_VECTOR=(NADD=PROCEDURE,-
NCONC=PROCEDURE,-
NADDRET=PROCEDURE,-
NCONCRET=PROCEDURE,-
NADD1=PROCEDURE,-
NCONCX=PROCEDURE,-
NRECMOD=PROCEDURE)
$
$ define/nolog ncshr "''f$parse("ncshr.exe")'"
$ exit
JC.java:
import java.io.UnsupportedEncodingException;
import java.text.DateFormat;;
import java.text.SimpleDateFormat;;
import java.util.Date;
import dk.vajhoej.record.FieldType;
import dk.vajhoej.record.RecordException;
import dk.vajhoej.record.Struct;
import dk.vajhoej.record.StructField;
import static dk.vajhoej.vms.call.VMS.*;
public class JC {
//--
// in integer arguments
//--
private static void test1() {
int a = 123;
int b = 456;
int stat = call("ncshr", "NADD", pass(new LongWord(a)).byValue().readOnly(),
pass(new LongWord(b)).byValue().readOnly());
}
//--
// in character arguments
//--
private static void test2() throws UnsupportedEncodingException {
String sa = "ABC";
String sb = "DEF";
int stat = call("ncshr", "NCONC", pass(new NullTermCharacterString(sa)).byReference().readOnly(),
pass(new NullTermCharacterString(sb)).byReference().readOnly());
}
//--
// in and out integer arguments
//--
private static void test3() {
int a = 123;
int b = 456;
LongWord cwrap = new LongWord();
int stat = call("ncshr", "NADDRET", pass(new LongWord(a)).byValue().readOnly(),
pass(new LongWord(b)).byValue().readOnly(),
pass(cwrap).byReference().writeOnly());
int c = cwrap.getValue();
System.out.printf("C gave : %d + %d = %d\n", a, b, c);
}
//--
// in and out character arguments
//--
private static void test4() throws UnsupportedEncodingException {
String sa = "ABC";
String sb = "DEF";
NullTermCharacterString cswrap = new NullTermCharacterString(1024);
int stat = call("ncshr", "NCONCRET", pass(new NullTermCharacterString(sa)).byReference().readOnly(),
pass(new NullTermCharacterString(sb)).byReference().readOnly(),
pass(cswrap).byReference().writeOnly());
String sc = cswrap.toString();
System.out.printf("C gave : %s + %s = %s\n", sa, sb, sc);
}
//--
// inout integer argument
//--
private static void test5() {
int v = 123;
LongWord vwrap = new LongWord(v);
int stat = call("ncshr", "NADD1", pass(vwrap).byReference().readWrite());
v = vwrap.getValue();
System.out.printf("C gave : %d\n", v);
}
//--
// inout character argument
//--
private static void test6() throws UnsupportedEncodingException {
String s = "ABC";
NullTermCharacterString swrap = new NullTermCharacterString(s, 1024);
int stat = call("ncshr", "NCONCX", pass(swrap).byReference().readWrite());
s = swrap.toString();
System.out.printf("C gave : %s\n", s);
}
//--
// inout record argument
//--
private static DateFormat df = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss");
@Struct
public static class MyRec {
@StructField(n=0, type=FieldType.INT1)
private int b1;
@StructField(n=1, type=FieldType.INT1)
private int b2;
@StructField(n=2, type=FieldType.INT2)
private int w;
@StructField(n=3, type=FieldType.INT4)
private int lw;
@StructField(n=4, type=FieldType.UNIXTIME)
private Date t;
@StructField(n=5, type=FieldType.FIXSTRNULTERM, length=8)
private String s;
public MyRec() {
this(0, 0, 0, 0, null, null);
}
public MyRec(int b1, int b2, int w, int lw, Date t, String s) {
this.b1 = b1;
this.b2 = b2;
this.w = w;
this.lw = lw;
this.t = t;
this.s = s;
}
public int getB1() {
return b1;
}
public void setB1(int b1) {
this.b1 = b1;
}
public int getB2() {
return b2;
}
public void setB2(int b2) {
this.b2 = b2;
}
public int getW() {
return w;
}
public void setW(int w) {
this.w = w;
}
public int getLw() {
return lw;
}
public void setLw(int lw) {
this.lw = lw;
}
public Date getT() {
return t;
}
public void setT(Date t) {
this.t = t;
}
public String getS() {
return s;
}
public void setS(String s) {
this.s = s;
}
@Override
public String toString() {
return String.format("(%d,%d,%d,%d,%s,%s)", b1, b2, w, lw, df.format(t), s);
}
}
@SuppressWarnings("unchecked")
private static void test7() throws RecordException {
MyRec r = new MyRec(1, 2, 3, 123, null, "ABC");
Block rwrap = new Block(r);
int stat = call("ncshr", "NRECMOD", pass(rwrap).byReference().readWrite());
r = (MyRec)rwrap.getObject(MyRec.class);
System.out.printf("C gave : %s\n", r);
}
public static void main(String[] args) throws UnsupportedEncodingException, RecordException {
test1();
test2();
test3();
test4();
test5();
test6();
test7();
}
}
Build and run:
$ javac -cp /vmsjavacallpath/vmscall.jar:/vmsjavacallpath/record.jar JC.java
$ java -cp .:/vmsjavacallpath/vmscall.jar:/vmsjavacallpath/record.jar JC
JC.groovy:
import java.text.*
import java.util.*
import dk.vajhoej.record.*
import static dk.vajhoej.vms.call.VMS.*
//--
// in integer arguments
//--
def test1() {
a = 123
b = 456
stat = call("ncshr", "NADD", pass(new LongWord(a)).byReference().readOnly(),
pass(new LongWord(b)).byReference().readOnly())
}
//--
// in character arguments
//--
def test2() {
sa = "ABC"
sb = "DEF"
stat = call("ncshr", "NCONC", pass(new NullTermCharacterString(sa)).byReference().readOnly(),
pass(new NullTermCharacterString(sb)).byReference().readOnly())
}
//--
// in and out integer arguments
//--
def test3() {
a = 123
b = 456
cwrap = new LongWord()
stat = call("ncshr", "NADDRET", pass(new LongWord(a)).byReference().readOnly(),
pass(new LongWord(b)).byReference().readOnly(),
pass(cwrap).byReference().writeOnly())
c = cwrap.getValue()
printf("C gave : %d + %d = %d\n", a, b, c)
}
//--
// in and out character arguments
//--
def test4() {
sa = "ABC"
sb = "DEF"
cswrap = new NullTermCharacterString(1024)
stat = call("ncshr", "NCONCRET", pass(new NullTermCharacterString(sa)).byReference().readOnly(),
pass(new NullTermCharacterString(sb)).byReference().readOnly(),
pass(cswrap).byReference().writeOnly())
sc = cswrap.toString()
printf("C gave : %s + %s = %s\n", sa, sb, sc)
}
//--
// inout integer argument
//--
def test5() {
v = 123
vwrap = new LongWord(v)
stat = call("ncshr", "NADD1", pass(vwrap).byReference().readWrite())
v = vwrap.getValue()
printf("C gave : %d\n", v)
}
//--
// inout character argument
//--
def test6() {
s = "ABC"
swrap = new NullTermCharacterString(s, 1024)
stat = call("ncshr", "NCONCX", pass(swrap).byReference().readWrite())
s = swrap.toString()
printf("C gave : %s\n", s)
}
//--
// inout record argument
//--
@Struct
class MyRec {
static DateFormat df = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss")
@StructField(n=0, type=FieldType.INT1)
int b1
@StructField(n=1, type=FieldType.INT1)
int b2
@StructField(n=2, type=FieldType.INT2)
int w
@StructField(n=3, type=FieldType.INT4)
int lw
@StructField(n=4, type=FieldType.UNIXTIME)
Date t
@StructField(n=5, type=FieldType.FIXSTR, length=8, pad=true, padchar=' ')
String s
@Override
String toString() {
return String.format("(%d,%d,%d,%d,%s,%s)", b1, b2, w, lw, df.format(t), s)
}
}
def test7() {
r = new MyRec(b1: 1, b2: 2, w: 3, lw: 123, t: null, s: "ABC")
rwrap = new Block(r)
stat = call("ncshr", "NRECMOD", pass(rwrap).byReference().readWrite())
r = (MyRec)rwrap.getObject(MyRec.class)
printf("C gave : %s\n", r)
}
test1()
test2()
test3()
test4()
test5()
test6()
test7()
Run:
$ groovy_cp = "/vmsjavacallpath/vmscall.jar:/vmsjavacallpath/record.jar"
$ groovy JC.groovy
Version | Date | Description |
---|---|---|
1.0 | June 6th 2024 | Initial version |
See list of all articles here
Please send comments to Arne Vajhøj