499 lines
17 KiB
C
499 lines
17 KiB
C
#define ident "1A05"
|
||
#ifdef VAXC
|
||
#module C_INTERFACES ident
|
||
#endif
|
||
#ifdef __DECC
|
||
#pragma module C_INTERFACES ident
|
||
#endif
|
||
/*
|
||
** +--------------------------------------------------------------+
|
||
** | Paul Scherrer Institute |
|
||
** | Computing Section |
|
||
** | |
|
||
** | This software may be used freely by non-profit organizations.|
|
||
** | It may be copied provided that the name of P.S.I. and of the |
|
||
** | author is included. Neither P.S.I. nor the author assume any |
|
||
** | responsibility for the use of this software outside of P.S.I.|
|
||
** +--------------------------------------------------------------+
|
||
**
|
||
** Module Name . . . . . . . . : [...LIB.SINQ]C_INTERFACES.C
|
||
**
|
||
** Author . . . . . . . . . . : D. Maden
|
||
** Date of creation . . . . . . : Nov 1993
|
||
**
|
||
** C_INTERFACES.C provides some routines which make it easier for C programs
|
||
** to call some of the Fortran routines in SINQ.OLB.
|
||
**
|
||
** To include this module in SINQ.OLB, use:
|
||
|
||
$ import tasmad
|
||
$ define/job sinq_c_tlb mad_lib:sinq_c_tlb.tlb
|
||
$ define/job sinq_olb mad_lib:sinq.olb
|
||
$ @lnsa09::tasmad_disk:[mad.psi.lib.sinq]sinq_olb c_interfaces debug
|
||
$
|
||
$ define/job sinq_olb mad_lib:sinq.olb
|
||
$ @lnsa09::tasmad_disk:[mad.psi.lib.sinq]sinq_olb c_interfaces
|
||
|
||
**
|
||
** Updates:
|
||
** 1A01 16-Nov-1993 DM. Initial version.
|
||
** 1A02 24-Nov-1994 DM. Make compatible with DEC C (as opposed to VAX C)
|
||
** 1A03 28-Nov-1994 DM. Add the TT_PORT_... entry points.
|
||
**====================================================================
|
||
** The following entry pointd are included:
|
||
** C_log_arr_get : interface routine from C to LOG_ARR_GET.
|
||
** C_log_flt_get : interface routine from C to LOG_FLT_GET.
|
||
** C_log_int_get : interface routine from C to LOG_INT_GET.
|
||
** C_log_str_get : interface routine from C to LOG_STR_GET.
|
||
**
|
||
** C_str_edit : interface routine to STR_EDIT.
|
||
**
|
||
** C_tt_port_connect : interface routine to TT_PORT_CONNECT.
|
||
** C_tt_port_disconnect: interface routine to TT_PORT_DISCONNECT.
|
||
** C_tt_port_io : interface routine to TT_PORT_IO.
|
||
** C_tt_port_config : interface routine to TT_PORT_CONFIG.
|
||
**====================================================================
|
||
** Global Definitions
|
||
*/
|
||
#ifdef VAXC
|
||
#include stdio
|
||
#include descrip
|
||
#include string
|
||
#include sinq_prototypes
|
||
#else
|
||
#include <stdio.h>
|
||
#include <sys/descrip.h>
|
||
#include <sys/string.h>
|
||
#include <sinq_prototypes.h>
|
||
#endif
|
||
/*--------------------------------------------------------------------------
|
||
** Global Variables
|
||
*/
|
||
extern int C_gbl_status = 0;
|
||
extern struct dsc$descriptor_s C_name_desc = { 0,
|
||
DSC$K_DTYPE_T,
|
||
DSC$K_CLASS_S,
|
||
0
|
||
};
|
||
|
||
/*--------------------------------------------------------------------------
|
||
** Old-style prototypes of routines which we are
|
||
** bridging to.
|
||
*/
|
||
int log_arr_get();
|
||
int log_int_get();
|
||
int log_flt_get();
|
||
int log_str_get();
|
||
|
||
int str_edit();
|
||
|
||
int tt_port_connect();
|
||
int tt_port_disconnect();
|
||
int tt_port_io();
|
||
int tt_port_config();
|
||
/*--------------------------------------------------------------------------*/
|
||
int C_log_arr_get(char *name, int arr_size, int *value, int indx)
|
||
{
|
||
/* =============
|
||
**
|
||
** This routine is useful for calling LOG_ARR_GET from a C program.
|
||
**
|
||
** Inputs:
|
||
** name - a pointer to the zero-terminated logical name.
|
||
** arr_size - the number of elements in the array value.
|
||
** indx - the index of the logical name.
|
||
** Outputs:
|
||
** value - an array of size arr_size set to the values converted
|
||
** to binary.
|
||
** Return status:
|
||
** the return status of the function is zero (false) if LOG_ARR_GET
|
||
** returns an error (even) condition code.
|
||
** Global variables:
|
||
** C_gbl_status - set to the VAX/VMS return status of LOG_ARR_GET.
|
||
** C_name_desc - set up as a string descriptor for name. It can
|
||
** be used to generate an error message if return status == 0.
|
||
*/
|
||
C_name_desc.dsc$w_length = strlen(name);
|
||
C_name_desc.dsc$a_pointer = name;
|
||
|
||
C_gbl_status = log_arr_get(&C_name_desc, &arr_size, value, &indx);
|
||
|
||
return (C_gbl_status & 1);
|
||
}
|
||
|
||
/*--------------------------------------------------------------------------*/
|
||
int C_log_int_get(char *name, long int *value, int indx)
|
||
{
|
||
/* =============
|
||
**
|
||
** This routine is useful for calling LOG_INT_GET from a C program.
|
||
**
|
||
** Inputs:
|
||
** name - a pointer to the zero-terminated logical name.
|
||
** indx - the index of the logical name.
|
||
** Outputs:
|
||
** value - the value of the logical converted to binary.
|
||
** Return status:
|
||
** the return status of the function is zero (false) if LOG_INT_GET
|
||
** returns an error (even) condition code.
|
||
** Global variables:
|
||
** C_gbl_status - set to the VAX/VMS return status of LOG_INT_GET.
|
||
** C_name_desc - set up as a string descriptor for name. It can
|
||
** be used to generate an error message if return status == 0.
|
||
*/
|
||
C_name_desc.dsc$w_length = strlen(name);
|
||
C_name_desc.dsc$a_pointer = name;
|
||
|
||
C_gbl_status = log_int_get(&C_name_desc, value, &indx);
|
||
|
||
return (C_gbl_status & 1);
|
||
}
|
||
|
||
/*--------------------------------------------------------------------------*/
|
||
int C_log_flt_get(char *name, float *value, int indx)
|
||
{
|
||
/* =============
|
||
**
|
||
** This routine is useful for calling LOG_FLT_GET from a C program.
|
||
**
|
||
** Inputs:
|
||
** name - a pointer to the zero-terminated logical name.
|
||
** indx - the index of the logical name.
|
||
** Outputs:
|
||
** value - the value of the logical converted to binary.
|
||
** Return status:
|
||
** the return status of the function is zero (false) if LOG_FLT_GET
|
||
** returns an error (even) condition code.
|
||
** Global variables:
|
||
** C_gbl_status - set to the VAX/VMS return status of LOG_FLT_GET.
|
||
** C_name_desc - set up as a string descriptor for name. It can
|
||
** be used to generate an error message if return status == 0.
|
||
*/
|
||
C_name_desc.dsc$w_length = strlen(name);
|
||
C_name_desc.dsc$a_pointer = name;
|
||
|
||
C_gbl_status = log_flt_get(&C_name_desc, value, &indx);
|
||
|
||
return (C_gbl_status & 1);
|
||
}
|
||
|
||
/*--------------------------------------------------------------------------*/
|
||
int C_log_str_get(char *name, char *value, int val_size, int indx)
|
||
{
|
||
/* =============
|
||
**
|
||
** This routine is useful for calling LOG_STR_GET from a C program.
|
||
**
|
||
** Inputs:
|
||
** name - a pointer to the zero-terminated logical name.
|
||
** val_size - the size of the value string.
|
||
** indx - the index of the logical name.
|
||
** Outputs:
|
||
** value - zero-terminated string giving the value of the logical.
|
||
** Trailing space characters will have been stripped.
|
||
** Return status:
|
||
** the return status of the function is zero (false) if LOG_STR_GET
|
||
** returns an error (even) condition code.
|
||
** Global variables:
|
||
** C_gbl_status - set to the VAX/VMS return status of LOG_STR_GET.
|
||
** C_name_desc - set up as a string descriptor for name. It can
|
||
** be used to generate an error message if return status == 0.
|
||
*/
|
||
struct dsc$descriptor_s my_val_desc = { 0,
|
||
DSC$K_DTYPE_T,
|
||
DSC$K_CLASS_S,
|
||
0
|
||
};
|
||
|
||
C_name_desc.dsc$w_length = strlen(name);
|
||
C_name_desc.dsc$a_pointer = name;
|
||
|
||
my_val_desc.dsc$w_length = val_size - 1;
|
||
my_val_desc.dsc$a_pointer = value;
|
||
|
||
C_gbl_status = log_str_get(&C_name_desc, &my_val_desc, &indx);
|
||
value[val_size - 1] = 0; /* Zero-terminate the string */
|
||
|
||
if (C_gbl_status & 1) { /* If success, strip trailing spaces */
|
||
while ((strlen(value) > 0) && (value[strlen(value) - 1] == ' ')) {
|
||
value[strlen(value) - 1] = 0;
|
||
}
|
||
}
|
||
return (C_gbl_status & 1);
|
||
}
|
||
|
||
/*--------------------------------------------------------------------------*/
|
||
int C_str_edit(char *out, char *in, char *ctrl, int *length)
|
||
{
|
||
/* ==========
|
||
**
|
||
** This routine is useful for calling STR_EDIT from a C program.
|
||
**
|
||
** Inputs:
|
||
** in - the string to be edited.
|
||
** ctrl - the string specifying what editing is to be done.
|
||
** Outputs:
|
||
** out - the edited string. The maximum size of this string must
|
||
** be specified as input parameter *length. The string
|
||
** will be zero terminated on return.
|
||
** Modified:
|
||
** *length - an integer specifying, on input, the length of "out" in
|
||
** bytes. This must include room for the zero termination.
|
||
** On return, length will be set to the number of characters
|
||
** copied to "out" (not counting the zero termination byte).
|
||
** Return status:
|
||
** the return status of the function is zero (false) if STR_EDIT
|
||
** returns an error (even) condition code.
|
||
** Global variables:
|
||
** C_gbl_status - set to the VAX/VMS return status of STR_EDIT.
|
||
*/
|
||
struct dsc$descriptor_s out_desc = { 0,
|
||
DSC$K_DTYPE_T,
|
||
DSC$K_CLASS_S,
|
||
0
|
||
};
|
||
struct dsc$descriptor_s in_desc = { 0,
|
||
DSC$K_DTYPE_T,
|
||
DSC$K_CLASS_S,
|
||
0
|
||
};
|
||
struct dsc$descriptor_s ctrl_desc = { 0,
|
||
DSC$K_DTYPE_T,
|
||
DSC$K_CLASS_S,
|
||
0
|
||
};
|
||
|
||
out_desc.dsc$w_length = *length - 1;
|
||
out_desc.dsc$a_pointer = out;
|
||
|
||
in_desc.dsc$w_length = strlen(in);
|
||
in_desc.dsc$a_pointer = in;
|
||
|
||
ctrl_desc.dsc$w_length = strlen(ctrl);
|
||
ctrl_desc.dsc$a_pointer = ctrl;
|
||
|
||
C_gbl_status = str_edit(&out_desc, &in_desc, &ctrl_desc, length);
|
||
if (*length >= 0) { /* zero-terminate the output string */
|
||
out[*length] = '\0';
|
||
} else {
|
||
out[0] = '\0';
|
||
}
|
||
|
||
return (C_gbl_status & 1);
|
||
}
|
||
|
||
/*--------------------------------------------------------------------------*/
|
||
int C_tt_port_connect(int *hndl, int *chan, char *lognam, char *pwd)
|
||
{
|
||
/* =================
|
||
**
|
||
** This routine is useful for calling TT_PORT_CONNECT from a C program.
|
||
**
|
||
** Inputs:
|
||
** lognam - a zero-terminated string specifying a logical name which
|
||
** defines the RS-232-C port to be connected. See description
|
||
** of TT_PORT_CONNECT for full details.
|
||
** pwd - a zero-terminated string specifying an optional password.
|
||
** This is the password associated with a terminal server
|
||
** service. See description of TT_PORT_CONNECT for full
|
||
** details. Specify NULL if no password.
|
||
** Outputs:
|
||
** hndl - an integer handle identifying the connection. It will be
|
||
** the address of a dynamically allocated data structure.
|
||
** chan - an integer (actually only 16 bit) giving the I/O channel
|
||
** associated with the connection. This can be used in QIO
|
||
** system calls to the terminal driver.
|
||
** Return status:
|
||
** the return status of the function is zero (false) if TT_PORT_CONNECT
|
||
** returns an error (even) condition code.
|
||
** Global variables:
|
||
** C_gbl_status - set to the VAX/VMS return status of TT_PORT_CONNECT.
|
||
*/
|
||
struct dsc$descriptor_s lognam_desc = { 0,
|
||
DSC$K_DTYPE_T,
|
||
DSC$K_CLASS_S,
|
||
0
|
||
};
|
||
struct dsc$descriptor_s pwd_desc = { 0,
|
||
DSC$K_DTYPE_T,
|
||
DSC$K_CLASS_S,
|
||
0
|
||
};
|
||
lognam_desc.dsc$w_length = strlen(lognam);
|
||
lognam_desc.dsc$a_pointer = lognam;
|
||
|
||
if (pwd != NULL) {
|
||
pwd_desc.dsc$w_length = strlen(pwd);
|
||
pwd_desc.dsc$a_pointer = pwd;
|
||
C_gbl_status = tt_port_connect(hndl, chan, &lognam_desc, &pwd_desc);
|
||
} else {
|
||
C_gbl_status = tt_port_connect(hndl, chan, &lognam_desc, NULL);
|
||
}
|
||
|
||
return (C_gbl_status & 1);
|
||
}
|
||
|
||
/*--------------------------------------------------------------------------*/
|
||
int C_tt_port_disconnect(int *hndl)
|
||
{
|
||
/* ====================
|
||
**
|
||
** This routine is useful for calling TT_PORT_DISCONNECT from a C program.
|
||
**
|
||
** Inputs:
|
||
** hndl - the integer handle identifying the connection as returned
|
||
** by C_tt_port_connect. It is the address of a dynamically
|
||
** allocated data structure which will also be released
|
||
** after the connection has been closed.
|
||
** Return status:
|
||
** the return status of the function is zero (false) if TT_PORT_DISCONNECT
|
||
** returns an error (even) condition code.
|
||
** Global variables:
|
||
** C_gbl_status - set to the VAX/VMS return status of TT_PORT_DISCONNECT.
|
||
*/
|
||
C_gbl_status = tt_port_disconnect(hndl);
|
||
|
||
return (C_gbl_status & 1);
|
||
}
|
||
|
||
/*--------------------------------------------------------------------------*/
|
||
int C_tt_port_io(
|
||
/* ============
|
||
*/ int *hndl,
|
||
char *rqst, char *term, char *answ, int *answ_len, /* Attention -- Read/Write argument!! */
|
||
int flush, int tmo)
|
||
{
|
||
/*
|
||
** This routine is useful for calling TT_PORT_IO from a C program.
|
||
** Refer to the DELTAT.OLB description of TT_PORT_IO to clarify any
|
||
** uncertainties in the following description. Note that all arguments
|
||
** must be present (there is no portable method in C of getting the
|
||
** number of arguments in the call!).
|
||
** Inputs:
|
||
** hndl - the integer handle identifying the connection as returned
|
||
** by C_tt_port_connect.
|
||
** rqst - an optional zero-terminated string specifying a character
|
||
** string to be sent to the port. Specify NULL to not send
|
||
** any characters to the port.
|
||
** term - an optional zero-terminated string specifying a list of
|
||
** terminating characters for input read from the port.
|
||
** Specify NULL to terminate input on an exact character cnt.
|
||
** flush - an integer specifying if the type-ahead buffer should be
|
||
** flushed before the operation. If non-zero, the buffer
|
||
** is flushed.
|
||
** tmo - an integer (recommended value = 2) specifying a read
|
||
** time-out in seconds. Zero or negative indicates infinity.
|
||
** Outputs:
|
||
** answ - an optional string buffer to receive characters read from
|
||
** the port. If answ is not NULL, answ_len must also be
|
||
** not NULL. On return, answ will be zero terminated. The
|
||
** terminating character, if any (there is no terminating
|
||
** char if the buffer overflows) and if there is room in
|
||
** the buffer, will follow the zero character. No padding is
|
||
** done. If answ is NULL, no characters are read from the
|
||
** port.
|
||
** Modify:
|
||
** answ_len - an integer specifying, on input, the length of answ in
|
||
** bytes. This must include room for the zero termination.
|
||
** On return, answ_len will be set to the number of
|
||
** characters read (not counting the zero termination byte or
|
||
** any terminating character).
|
||
** Return status:
|
||
** the return status of the function is zero (false) if TT_PORT_IO
|
||
** returns an error (even) condition code.
|
||
** Global variables:
|
||
** C_gbl_status - set to the VAX/VMS return status of TT_PORT_IO.
|
||
*/
|
||
struct dsc$descriptor_s rqst_desc = { 0,
|
||
DSC$K_DTYPE_T,
|
||
DSC$K_CLASS_S,
|
||
0
|
||
};
|
||
struct dsc$descriptor_s term_desc = { 0,
|
||
DSC$K_DTYPE_T,
|
||
DSC$K_CLASS_S,
|
||
0
|
||
};
|
||
struct dsc$descriptor_s answ_desc = { 0,
|
||
DSC$K_DTYPE_T,
|
||
DSC$K_CLASS_S,
|
||
0
|
||
};
|
||
char *my_rqst = NULL;
|
||
char *my_term = NULL;
|
||
char *my_answ = NULL;
|
||
|
||
int my_answ_len = 0;
|
||
int my_flush = 1;
|
||
int my_tmo = 2;
|
||
|
||
my_tmo = tmo;
|
||
if (my_tmo < 0)
|
||
my_tmo = 0;
|
||
my_flush = flush;
|
||
if (my_flush != 0)
|
||
my_flush = 1;
|
||
if (answ != NULL) {
|
||
if (answ_len == 0) {
|
||
printf("C_tt_port_io -- argument error.\n");
|
||
printf(" %s\n",
|
||
"answ_len must be present if answ is present.");
|
||
C_gbl_status = FALSE;
|
||
return FALSE;
|
||
}
|
||
answ_desc.dsc$w_length = *answ_len - 1;
|
||
answ_desc.dsc$a_pointer = answ;
|
||
}
|
||
if (term != NULL) {
|
||
term_desc.dsc$w_length = strlen(term);
|
||
term_desc.dsc$a_pointer = term;
|
||
}
|
||
if (rqst != NULL) {
|
||
rqst_desc.dsc$w_length = strlen(rqst);
|
||
rqst_desc.dsc$a_pointer = rqst;
|
||
}
|
||
C_gbl_status = tt_port_io(hndl, &rqst_desc, &term_desc,
|
||
&answ_desc, &my_answ_len, &my_flush, &my_tmo);
|
||
if (answ_desc.dsc$w_length > 0) { /* Process any input string */
|
||
if (answ_desc.dsc$w_length > my_answ_len) { /* Room for terminator? */
|
||
answ[my_answ_len + 1] = answ[my_answ_len]; /* Yes, so move it. */
|
||
}
|
||
answ[my_answ_len] = '\0'; /* Put in null terminator */
|
||
*answ_len = my_answ_len; /* Return value to caller */
|
||
}
|
||
|
||
return (C_gbl_status & 1);
|
||
}
|
||
|
||
/*--------------------------------------------------------------------------*/
|
||
int C_tt_port_config(
|
||
/* ================
|
||
*/ int *hndl,
|
||
int mask)
|
||
{
|
||
/*
|
||
** This routine is useful for calling TT_PORT_CONFIG from a C program.
|
||
** Refer to the DELTAT.OLB description of TT_PORT_CONFIG to clarify any
|
||
** uncertainties in the following description.
|
||
** Inputs:
|
||
** hndl - the integer handle identifying the connection as returned
|
||
** by C_tt_port_connect.
|
||
** mask - an integer specifying the configuration options. Set bits
|
||
** TT_PORT__NO_RETRY = 0x0001 to suppress retries on error
|
||
** TT_PORT__NO_SIG = 0x0002 to suppress signals on error
|
||
** Outputs:
|
||
** None
|
||
** Modify:
|
||
** None
|
||
** Return status:
|
||
** always non-zero (true).
|
||
** Global variables:
|
||
** C_gbl_status - set to the VAX/VMS return status of TT_PORT_CONFIG.
|
||
*/
|
||
C_gbl_status = tt_port_config(hndl, &mask);
|
||
|
||
return (C_gbl_status & 1);
|
||
}
|
||
|
||
/*=========================================== End of C_INTERFACES.C ========*/
|