#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 #include #include #include #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 ========*/