$ HELP/LIBRARY=MDS$ROOT:[SYSHLP]MDSPLUS.HLB TDISHR
C-like syntax
Variables
>>>>>>>>>WARNING, they have side effects!!!
You may store any MDSplus data type in a variable and then reference it as
you need it in other expressions.
>>>>>>>>>WARNING, the order of operations may not be clear (to you or the
compiler), so be careful about assigning data to a variable and using the
variable in the same expression.
COMMA, VECTOR, and statements are left to right but argments of functions
may be used in any order.
There are two forms of variables: private and public. The usual, private
variables are seen only by your current FUN. Whereas, public variables can be
seen by all programs. Anywhere a VAR like _X can be used, you may use
PRIVATE _X or PUBLIC _X to distinguish the one you want. Otherwise on reading,
_X looks for PRIVATE _X first and then PUBLIC _X. On writing, _X will be stored
in the private list unless it was a modify operation like _X++ or _X+=6.
>>>>>>>>>WARNING, always use PUBLIC for public variables to help you analyze
the code later.
All user variables should begin with an underscore (_);
Integers must begin with a number.
Prefixes designate base and are 0B for binary, 0O for octal, 0X for
hexadecimal, and none for decimal.
Suffixes designated data type: BU for byte_unsigned, WU for word_unsigned,
LU for long_unsigned, QU for quadword_unsigned, OU for octaword_unsigned, B
for byte, W for word, L for long, Q for quadword, and O for octaword. No suffix
is
type L. You may use UB instead of BU for byte_unsigned and SB or BS instead of
B for byte. After 0X use SB for signed bytes because the B looks like a digit.
Floating point numbers must have a decimal point or an exponent with
following optionally signed digit or digits and at least one digit.
The exponent designator is E or F for standard precision, D for double, G
for
wide-exponent double.
Without an exponent, standard precision is assumed.
Complex numbers must be formed with the function CMPLX(real,imag).
WARNING, you may specify D_COMPLEX and others but the precision of the
arguments is determined by each exponent letter.
Characters or text may be enclosed in single quotes (apostrophes) or double
quotes. TDISHR uses the CC-style designation of
Octal controls are limited to three digits or the first non-octal one.
Adjacent text strings (possibly with white space between) are concatenated.
This allows breaking of strings across more than one line.
Otherwise, two literals may not be adjacent--bad syntax.
CC-use
To eliminate using the compiler you could write functions to be
evaluated. This involves many descriptors and pointers, see OPC$.
Between the inefficiency of compilation and the difficulty of function
coding is the method of direct calls to the TDISHR library. Like
Operations like + have special names like TDI$ADD, see Precedence.
Calls
This example would be easier to code in VAX Fortran.
DEFINE C$LIBRARY MDS$ROOT:[SYSLIB]MDSDEF.TLB
before compiling with CC the following code excerpt:
The included files define the descriptor structures, descrip from
VAXCDEF and tdescrip from MDSDEF. The global reference is to TDISHR and
the function number is used by EVALUATE to do the operation. The node's
data is fetched and its data type, and possibly two's data type, are
converted to match. The addition is done and the result is embedded in
units and signal descriptions as needed. The result is then matched to the
output descriptor's data class and type. The output descriptor must be
class-XD if the result is more complicated than a standard scalar.
The input arguments could be "static const" because they are read only.
To eliminate using the compiler you could write functions to be
evaluated. This involves many descriptors and pointers, see OPC$.
Between the inefficiency of compilation and the difficulty of function
coding is the method of direct calls to the TDISHR library.
status = TDI$ADD(%DESCR(first), %DESCR(second), output_dsc)
Other than special calls directly into TDISHR, you call routines by
names like TDI$xxx, where xxx is the function to be performed. Each
routine returns a VMS-type status code as its function value. The
arguments are the addresses of descriptors of each input with the final
argument being the one output descriptor.
Operations like + have special names like TDI$ADD, see Precedence.
WARNING each TDI routine must be declared as an Integer*4.
WARNING (Today, Fortran include file tdescrip does not exist.)
Calls
We could also have used
TDI$ADD(%descr(2), '\TOP.XRAY.CHAN_1:GAIN', out_dsc)
The included files define the descriptor structures. The external
reference is satisfied by TDISHR and the function number is used by
EVALUATE to do the operation. The node's data is fetched and its data
type, and possibly two's data type, are converted to match. The
addition is done and the result is embedded in units and signal
descriptions as needed. The result is then matched to the output
descriptor's data class and type. The output descriptor must be
class-XD if the result is more complicated than a standard scalar.
There is no way in VAX Fortran to "Data" (initialize) a record.
This is better done in C, if it is done at all.
SYS$GETMSG(%val(status), length_ret, text_ret, %val(15), ).
Operators with equal precedence are evaluated left to right (LR) or
right to left (RL). You may use F90 (/ for [, /) for ], and /= for !=.
Signals
In combining expressions with signals, generally a single signal will
dominate. When more than one signal is combined, only one signal can be
chosen. The signal selected will be the one with the smaller number of
elements as this limits the size of the result.
Spell out units with lowercase or better yet use the abbreviation.
Proper names are spelled in lowercase or abbreviated in uppercase.
The basic unit names are:
The supplementary unit names are:
The use of nonstandard names, like sec for second, will
inhibit the use of later (to be written) unit handling.
It is unlikely that Pa/torr will be recognized as unit-less,
it will be hard enough to see that V*A is W.
Restrain the use of multipliers. If you do use them, then:
>>>>>>>>>WARNING, use the preferred SI units:
Avoid cm for centimeter, use mm or m.
Avoid G or gauss, use T. (1T = 10000G, 1mT = 10G.)
Use of eV for electron volt may be necessary.
The abbreviation of millitorr is mtorr.
Conversions and simple arithmetic operations do not change the units.
For example, BYTE, ABS, and UNARY_MINUS keep the units.
The argument of mathematical operations like SIN(x) should not
have units because the number must be dimensionless.
Degrees are not recognized--Use SIND(x).
The units of a result are defined for some binary operations:
Addition and subtraction retain the units of a single WITH_UNITS
or if the units match. Otherwise, the result is an error and is
given the units "?".
Multiplication and division try to combine units.
Problems exist with SQRT, POWER, and PRODUCT. PRODUCT may have
an ill defined number of terms. (It depends on the MASK and
the number of $ROPRANDs.)
Additional information available:
TDI$CONVERT(%descr(IN),%descr(OUT))
TDI$CVT_DX_DX(%descr(IN),%ref(DTYPE),%descr(XD))
TDI$FAULT_CLEAR([%ref(NEW)])
TDI$FAULT_HANDLER(%ref(SIG_ARGS),%ref(MECH_ARGS))
TDI$GET_DATA(%ref(OMITS),%descr(IN),%descr(XD))
TDI$GET_FLOAT(%descr(IN),%ref(OUT))
TDI$GET_LONG(%descr(IN),%ref(OUT))
TDI$GET_NID(%descr(IN),%ref(OUT))
TDI$$INTRINSIC(%val(OPCODE),%val(NARG),%ref(LIST),%descr(OUT))
It is highly recommended that child or member nodes be marked.
Partial implementation:
No IO nor DECODE/ENCODE/STRING.
Statements not written: ON_ERROR WHERE.
Elementals: BITS NEAREST IS_IN.
F90: CSHIFT EOSHIFT PROJECT RANDOM_SEED
RESHAPE TRANSFER UNPACK
F90 system: DATE_AND_TIME SYSTEM_CLOCK.
Cross-element: CONVOLVE DERIVATIVE FFT INTEGRAL MEDIAN
RC_DROOP INTERSECT SMOOTH.
Matrix: INVERSE MATMUL SOLVE TRANSPOSE.
Interpolation: INTERPOL MAT_ROT MAT_ROT_INT REBIN.
No SUBSCRIPTS for variable store.
Axes are not propagated for most transforms.
No text to numerics, no Abs("123"). Numbers compiled OK.
Subscript should immediately follow name. Watch NOT[sub].
[non-VMS] generates VECTOR not APD.
APD is evaluated by VECTOR requiring DATA of objects.
No units for POWER SQRT and some transforms.
Quirk:
-128b is illegal because it is negative of "bad" 128b, etc.
APD: Array of Pointers to Descriptors
Local variables are to be used to optimize code by not recalculating
and for
writing repeated or more complicated expressions. They should not be used to
carry information across trees because access is then order dependent.
system variables will begin with a dollar sign ($).
Names beginning with alphabetics look like tree members.
The length must be less than 200.
Upper and lower cases are not distinct, thus _a and _A are the same.
Literals
Literals are constants written as text. Letters used to designate data type
and
base may be upper or lower case.
Glossary
control characters (\001 or \n),
the quoting character (\' or \"),
and the backslash (\\) itself.
Hexadecimal control characters (\x8c) must be used with care, because they
stop on the first non-hexadecimal character.
array... A collection of scalars in a multidimensional rectangle.
axis.... The independent variable.
bounds.. Array subscript limits, lower and upper.
byte.... Eight bits of information, one character, an integer.
C$LIBRARY A logical definition of a .TLB for #include files.
call.... To invoke a subroutine during program execution.
CC...... The C-language compiler.
class... The class of a block of memory, static, dynamic, array.
complex. Real and imaginary parts joined.
conforming The matching of shapes, a scalar matches any shape.
descrip. The header file defining VMS descriptor, dtype, class.
descriptor The description of the contents of a memory block.
dimension An independent axis of an array.
dtype... The kind of a block of memory. A data type like
long, usually a byte code.
dynamic. Data whose memory location is changable.
evaluate To remove references like NIDs, PATHs, and FUNCTIONs.
F90..... The Fortran 90 standard (as originally proposed).
float... A floating-point number, esp. a single-precision real.
function An opcode and arguments to determine a value.
include. A file .H for CC, .FOR for Fortran with definitions.
index... A subscript value.
integer. Whole numbers.
kind.... The data type of a block of memory. A data type like
long, usually a byte code.
length.. The number of bytes in an element.
logical. Variable with two states: true or false; low bit tested.
As opposed to CC-style that tests for zero.
matrix.. A two-dimensional array, usually.
MDSplus. The programs and libraries for data taking and analysis.
MDSLIB.. Routines easily called from VAX Fortran or IDL, etc.
MDSSHR.. Routines common to several MDSplus libraries.
missing. An omitted argument.
multiplier Array subscript number of values, upper-lower+1.
NID..... A node identifier, a number used in references in trees.
node.... A element of a tree with data and/or links to nodes.
numeric. Integer, real, or complex number.
OPC$.... Operation codes for TDISHR functions.
opcode.. An operation code identifying the action to take.
param... An independent value with textual and validation info.
path.... The textual name of a tree element.
pointer. The address of a memory object.
precedence The order operations are done without parentheses.
rank.... Dimensionality of an array. A scalar is rank 0.
real... An approximate number with exponent and fraction.
record.. A class-R descriptor or a data block on disk.
ROPRAND. The floating point reserved operand, a bad number.
Similar to Not-A-Number in Unix. Infinity exists on both systems.
scalar.. A single value.
shape... The extent of all dimensions of an object.
signal.. Data, including the raw data, and independent axes.
signal_VMS To notify routines of some condition like an error.
signed.. Integer forms with positive and negative numbers.
size.... The number of elements of an array; sometimes bytes.
static.. Data with fixed memory location.
status.. An integer identifying severity and text of an error.
subscript The offset along a dimension of an array.
tdescrip The header file defining MDS descriptor, dtype, class.
TDISHR.. Tree Data Interface sharable library.
tree.... A linked collection of nodes.
units... The physical measure associated with a number.
unsigned Integer forms ranging from 0 to 2^(number of bits)-1.
vector.. A linearly ordered list of scalars. A rank-one array.
window.. The region of an axis that is viewed.
word.... Two bytes of information, an integer.
XD...... A class of descriptor for dynamic storage.
The easiest calls are the MDSLIB routines.
Fortran-use
status = TDI$ADD(&first_dsc, &second_dsc, &output_dsc);
Other than special calls directly into TDISHR, you call routines by names
like TDI$xxx, where xxx is the function to be performed. Each routine
returns a VMS-type status code as its function value. The arguments are
the addresses of descriptors of each input with the final argument being
the one output descriptor.
As an example of TDISHR calls we will add 2 and a tree element.
MDSLIB
#include descrip
int call_test(struct dsc$descriptor *out_dsc_ptr)
{
static int const two = 2;
static struct dsc$descriptor two_dsc
= {0,DSC$K_DTYPE_L,DSC$K_CLASS_S,&two};
static $DESCRIPTOR(const elem_dsc, "\\TOP.XRAY.CHAN_1:GAIN");
int status;
status = TDI$ADD(&two_dsc, &elem_dsc, out_dsc_ptr);
return status;
}
As an example of MDSLIB calls we will add 2 and a tree element. The
experiment and shot are assumed identified elsewhere.
OPC$
#include descrip
int call_test(struct dsc$descriptor *out_dsc_ptr)
{
static $DESCRIPTOR(const expression,
"2+\\TOP.XRAY.CHAN_01:GAIN");
int status;
status = MDS$VALUE(&expression, out_dsc_ptr);
return status;
}
(This example would be easier to code in VAX Fortran.)
The most difficult form of coding is to define all relationships with
pointers in special (class-R) descriptors to other descriptors of VMS and
MDSplus data. As an example, we will add 2 and a tree element. Use DCL to
Status
#include descrip
#include tdescrip
int opc_test(struct dsc$descriptor *out_dsc_ptr)
{
globalref unsigned short OPC$ADD;
static int const two = 2;
static struct dsc$descriptor const two_dsc
= {sizeof(two),DSC$K_DTYPE_L,DSC$K_CLASS_S,&two};
static $DESCRIPTOR(const elem_dsc, "\\TOP.XRAY.CHAN_1:GAIN");
static struct dsc$descriptor_r const add_dsc
= {2,DSC$K_DTYPE_FUNCTION,DSC$K_CLASS_R,&OPC$ADD,2,0,
&two_dsc,&elem_dsc};
int status;
status = TDI$EVALUATE(&add_dsc, out_dsc_ptr);
return status;
}
Each TDISHR routine returns a longword VMS-type status.
The lowest bit is set (status & 1) if the operation succeeded.
Otherwise, the error may be signaled by LIB$SIGNAL(status) or its text
fetched by SYS$GETMSG(status, &length_ret, &text_dsc, 15, 0).
The easiest calls are the MDSLIB routines.
Precedence
As an example of TDISHR calls we will add 2 and a tree element.
MDSLIB
Integer function call_test(out_dsc)
Include 'FORSYSDEF.TLB($DSCDEF)'
Record /DSCDEF1/ out_dsc
Integer two /2/
Character*21 elem = '\TOP.XRAY.CHAN_1:GAIN'
call_test = TDI$ADD(%descr(two), %descr(elem), out_dsc);
Return
End
As an example of MDSLIB calls we will add 2 and a tree element. The
experiment and shot are assumed identified elsewhere.
OPC$
Integer function mds_test(dataid)
Integer dataid
mds_test = MDS$GET('2+\TOP.XRAY.CHAN_01:GAIN', dataid);
Return
End
The most difficult form of coding is to define all relationships with
pointers in special (class-R) descriptors to other descriptors of VMS and
MDSplus data. As an example, we will add 2 and a tree element. As of this
writing, there is no TDESCRIP definitions for Fortran use.
Status
Integer Function opc_test(out_dsc)
Include 'FORSYSDEF.TLB($DSCDEF)'
Include 'FORMDSDEF.TLB(tdescrip)'
Record /DSCDEF1/ out_dsc
External OPC$ADD
Integer two = 2
Character*21 elem = '\TOP.XRAY.CHAN_1:GAIN'
Record /DSC$DESCRIPTOR_R2/ add_dsc
add_dsc.dsc$w_length = 2
add_dsc.dsc$b_dtype = DSC$K_DTYPE_FUNCTION
add_dsc.dsc$b_class = DSC$K_CLASS_R
add_dsc.dsc$a_pointer = %loc(OPC$ADD)
add_dsc.dsc$b_ndesc = 2
add_dsc.dsc$a_dscptrs(1) = %loc(%descr(2))
add_dsc.dsc$a_dscptrs(2) = %loc(%descr(elem))
opc_test = TDI$EVALUATE(add_dsc, out_dsc);
Return
End
Each TDISHR routine returns a longword VMS-type status. The lowest
bit is set (status .AND. 1) if the operation succeeded. Otherwise, the error
may be signaled by LIB$SIGNAL(%val(status)) or its text fetched by
TDISHR supports many syntactical forms having different precedence.
Precedence determines the order operations are done when operators
are on both sides of a resolved portion of an expression. Thus, precedence
makes 2+3*4 have value 14 and not 20.
where x, y, or z are resolved expressions, f and v are variables, and s
and se are statements. Think about "-2.^-3^4". (Answer: -2.417852E24.)
group
function name symbol
(highest precedence)
-- grouping (none) (x)
LR postfix CALL(i,r,[x]...) i->r:type(x,...)
POST_DEC(v) v--
POST_INC(v) v++
SUBSCRIPT(x,y,...) x[y,...], x(/y,.../)
VECTOR(x,y,...) [x,y,...], (/x,y,.../)
RL unary INOT(x) ~x
NOT(x) !x, NOT x
PRE_DEC(v) --v
PRE_INC(v) ++v
UNARY_MINUS(x) -x
UNARY_PLUS(x) +x
RL power POWER(x,y) x^y, x**y
LR multiply MULTIPLY(x,y) x*y
DIVIDE(x,y) x/y
MOD(x,y) x MOD y
LR addition ADD(x,y) x+y
SUBTRACT(x,y) x-y
LR shift SHIFT_LEFT(x,y) x<<y
SHIFT_RIGHT(x,y) x>>y
LR concatenate CONCAT(x,y) x//y
LR subset IS_IN(x,y) x IS_IN y
LR inequality GE(x,y) x>=y, x GE y
GT(x,y) x>y, x GT y
LE(x,y) x<=y, x LE y
LT(x,y) x<y x LT y
LR equality EQ(x,y) x==y, x EQ y
NE(x,y) x!=y, x<>y, x/=y, x NE y
LR bit-AND IAND(x,y) x&y (see IAND etc.)
LR bit-EOR (see IEOR etc.)
LR bit-OR IOR(x,y) x|y (see IOR etc.)
LR equivalence EQV(x,y) x EQV y
NEQV(x,y) x NEQV y
LR logical-OR OR(x,y) x && y, x OR y
OR_NOT(x,y) x OR_NOT y
NOR(x,y) x NOR y
NOR_NOT(x,y) x NOR_NOT y
LR logical-AND AND(x,y) x || y, x AND y
AND_NOT(x,y) x AND_NOT y
NAND(x,y) x NAND y
NAND_NOT(x,y) x NAND_NOT y
RL promotion PROMOTE(x,y) x@y
RL conditional CONDITIONAL(y,z,x) x?y:z
RL range BUILD_RANGE(x,y,[z]) x..y, x..y..z, x:y, x:y:z
RL assignment EQUALS(v,x) v=x
EQUALS_FIRST(ADD(v,x)) v+=x, ... v MOD=x, ...
LR comma COMMA(x,y,...) x,y,...
LR statement (none) x;
STATEMENT(s,...) {s ...}
BREAK() BREAK;
CASE(x,s,...) CASE(x)s
CONTINUE() CONTINUE;
DEFAULT(s,...) CASE DEFAULT s
DO(x,s,...) DO{s...}WHILE(x);
FOR([x],[y],[z],s,...) FOR(x;y;z)s
FUN(f,s,v...) FUN f(v,...)s
PRIVATE FUN f(v,...)s
PUBLIC FUN f(v,...)s
GOTO(x) GOTO x;
IF(x,s,se) IF(x)s
IF(x)s ELSE se
LABEL(v,s,...) LABEL v: s
RETURN([x]) RETURN(x);
SWITCH(x,s,...) SWITCH(x) s
WHILE(x,s,...) WHILE(x)s
(lowest precedence)
A signal is data with its source (RAW is usually an intermediate
expression) and its DIMENSIONs. The dimensions are the independent axes
of the dependent data. For example, a waveform is a function of time and
the dimension is the time points at which the waveform was recorded.
Often this axis is a simple expression that can be expressed as a SLOPE or
RANGE.
Units
Units can be added to any data field by the WITH_UNITS descriptor.
Units are the "dimensions". (Be careful not to confuse this with the
word for the independent axis.) Units are like meters and seconds.
TDI_direct_calls
m meter kg kilogram s second
A ampere K kelvin mol mole
cd candela
rad radian sr steradian
Derived unit names are:
Hz hertz J joule N newton
Pa pascal W watt C coulomb
V volt (Omega) ohm S siemens
F farad Wb weber H henry
T tesla lm lumen lx lux
Bq becquerel Gy gray
Use star (*) for multiplication.
Use caret (^) to mark powers.
Use positive powers and precede negative ones by a slash (/).
f for femto, p for pico, n for nano, u for micro,
m for milli, k for kilo, M for mega, G for giga, and
T for tera are OK. (Micro is a Greek mu but u is readable.)
These routines directly enter TDISHR and have less error checking.
They do return a long status and must be declared as INTEGER*4 in
Fortran programs.
Restrictions
Trouble words for tree node names without preceding . or : are the
names of standard operations: NOT BREAK CONTINUE ELSE ELSEWHERE.