Files
sicspsi/sinqhm/sinqhm_client.c
cvs 064ec37e9a - Rearranged directory structure for forking out ANSTO
- Refactored site specific stuff into a site module
- PSI specific stuff is now in the PSI directory.
- The old version has been tagged with pre-ansto
2003-06-20 10:18:47 +00:00

3125 lines
104 KiB
C
Executable File
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#define IDENT "1C06"
/*---------------------------------------------------------------------------*/
#ifdef __DECC
#pragma module SinqHM_Client IDENT
#endif
/*
** Link_options - Here is the Linker Option File
**! sinqhm_client
**! sinq_olb/lib/inc=deltat_messages
**! pgplot_dir:cpgplot.olb/lib
**! pgplot_dir:grpckg.olb/lib
**! sys$share:decw$xlibshr/share
**!!
**!! To build SINQHM_CTRL on LNSA09
**!!
**!! $ import tasmad
**!! $ define/job deltat_c_tlb sinq_c_tlb
**!! $ sss := tas_src:[sinqhm]
**!! $ bui 'sss'sinqhm_client debug
** Link_options_end
**
** Building on Alpha OSF/1:
**
** cc -Dmain=MAIN__ -std1 -g -c -o sinqhm_client.o \
** -I/data/lnslib -I. \
** ~/SinqHM/sinqhm_client.c
** f77 -g -o ~/bin/sinqhm_client sinqhm_client.o \
** -L/public/lib -lsinq -lcpgplot -lpgplot -lX11
** rm sinqhm_client.o
**
** +--------------------------------------------------------------+
** | 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 . . . . . . . . : [...sinqhm]sinqhm_client.c
**
** Author . . . . . . . . . . : D. Maden
** Date of creation . . . . . . : Jan 1997
**
** SinqHM_Client is the main program of an Internet Client which transmits
** requests to a SinqHM server running on a front-end processor.
**
** Updates:
** 9-Jan-1997 DM. Initial version.
**
**====================================================================
*/
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <math.h>
#include <sys/socket.h>
#include <string.h>
#include <sys/types.h>
#include <X11/Intrinsic.h>
#ifdef __VMS
#include <pgplot_dir:cpgplot.h>
#else
#include <cpgplot.h>
#endif
/*
**==================== Global Definitions =====================================
*/
#include <sinq_prototypes.h>
#include "SinqHM_def.h"
#define uchar unsigned char
#define usint unsigned short int
#define uint unsigned int
#define NIL '\0'
#define NL '\n'
#define MAXERR 10
#define MAX_HIS 16
#define BSIZE ((128*1024)/512) /* Specify 128 kbyte buffer */
#ifndef True
#define True 1
#endif
#ifndef False
#define False 0
#endif
/*
** Define the Data Structures we need
*/
/*
**==================== Global Variables ======================================
*/
int My_errno, My_vaxc_errno;
struct req_buff_struct Req_buff;
struct rply_buff_struct Rply_buff;
int Verbose;
int Rmt_port;
int Pkt_size;
char Rmt_host[32];
int Rw_bytes_got, Rw_bytes_put;
static int Cnct_skt = 0; /* Connect socket */
static int Rw_skt = 0; /* Read/write socket */
int Dbg_mode; /* Setting of <strt_mode> in the SQHM_CNCT
** message to SINQHM server */
/*
** The buffer for holding Hist Mem data is pointed to
** by Hm_buff_addr. The number of bytes allocated is Hm_buff_size.
*/
void *Hm_buff_addr = NULL;
uint Hm_buff_size;
uint Hm_buff_used;
uint Hm_mode; /* Histogramming Mode of Histogram Memory */
uint N_hists; /* The number of histograms */
uint Hm_nbins; /* The number of bins per histogram */
uint Compress; /* The span of each bin */
uint Bytes_per_bin; /* The number of bytes per bin */
uint Curr_hist; /* The current histogram */
uint Max_block;
uint Lo_cntr;
uint Lo_bin;
uint Total_bytes;
int PGPLOT_started = 0;
float P1 = 2000000,
P2 = 10000,
P3 = 0,
P4 = 200000,
P5 = 500,
P6 = 0;
static XrmOptionDescRec OpTable_0[] = {
{"-name", ".name", XrmoptionSepArg, (XPointer) NULL},
{"-dbg", ".sqhmDebug", XrmoptionNoArg, (XPointer) "1"},
{"-debug", ".sqhmDebug", XrmoptionNoArg, (XPointer) "1"},
{"-h", ".sqhmHelp", XrmoptionNoArg, (XPointer) "1"},
{"-he", ".sqhmHelp", XrmoptionNoArg, (XPointer) "1"},
{"-hel", ".sqhmHelp", XrmoptionNoArg, (XPointer) "1"},
{"-help", ".sqhmHelp", XrmoptionNoArg, (XPointer) "1"},
{"-ho", ".sqhmHost", XrmoptionSepArg, (XPointer) NULL},
{"-hos", ".sqhmHost", XrmoptionSepArg, (XPointer) NULL},
{"-host", ".sqhmHost", XrmoptionSepArg, (XPointer) NULL},
{"-port", ".sqhmPort", XrmoptionSepArg, (XPointer) NULL},
{"-pktsize", ".sqhmPktSize", XrmoptionSepArg, (XPointer) NULL},
{"-size", ".sqhmPktSize", XrmoptionSepArg, (XPointer) NULL},
{"-v", ".sqhmVerbose", XrmoptionNoArg, (XPointer) "1"},
{"-?", ".sqhmHelpItem", XrmoptionSepArg, (XPointer) NULL},
};
/*
**=============================================================================
** Local routines.
**
** do_dump : Dump out the contents of the histogram buffer.
** do_load : Load the histogram buffer from a file.
** do_plot : Plot the data.
** do_project : Handle the "PROJECT" command.
** do_status : Get and display status of SinqHM_srv.
** do_1d : Handle the "READ" command.
** do_2d : Handle the "2D" command.
** do_2d_plot : Plot the data 2-dimensionally.
** exit_handler : Exit handler in case a forced exit is made.
** gen_data : Generate sum of 2 Lorenzians.
** gen_data_2d : Generate sum of 2 Lorenzians in pseudo 2-dim mode.
** get_recd : Read a record from file.
** new_config_quit : Quit because SinqHM config'n has changed.
** openConnection : Open connection to SinqHM.
** openConnectionGbl : Call openConnection then set up some globals.
** print_HM_mode : Interpret the HM configuration.
** print_uptime : Print out the up-time.
** read_hm : Read block of bins from SINQHM_SRV
** read_project : Read projected block of bins from SINQHM_SRV
** show_help : Display the help text.
** split_args : Parse a command line.
** write_hm : Write block of bins to SINQHM_SRV
**----------------------------------------------------------------------------
** Prototypes
*/
void do_dump (char *args);
void do_load (char *args, int dbg_mode);
void do_plot (uint first, uint n_bins, uint bytes_per_bin, uint total);
void do_project (char *args, int dbg_mode);
void do_status (int dbg_mode);
void do_1d (char *args, int dbg_mode);
void do_2d (char *args, int dbg_mode);
void do_2d_plot (uint f_hist, uint n_hists, uint f_bin, uint n_bins,
uint bytes_per_bin, uint total);
void exit_handler ();
void gen_data (char *args);
void gen_data_2d (char *args);
int get_check_resources (XrmDatabase *db,
char *appName,
int *argc,
char *argv[],
int verbose);
int get_recd (FILE *lun, char *recd, int recd_len);
void new_config_quit (char *txt);
int openConnection (char *node,
int *port,
int *pkt_size,
int mode,
struct rply_buff_struct *reply,
int verbose);
int openConnectionGbl (char *node,
int *port,
int *pkt_size,
int mode,
struct rply_buff_struct *reply,
int verbose);
void print_HM_mode (uint mode, int n_pad);
void print_uptime (FILE *lun, char *prefix, int secs, char *suffix);
int read_hm (char *buff,
uint hbuf_size,
uint f_bin,
uint n_bins,
uint hist_num,
uint *cntr_lo,
uint *cntr_hi);
int read_project (char *buff,
uint hbuf_size,
uint f_hist,
uint n_hists,
uint f_bin,
uint n_bins,
uint axis,
uint xdim,
uint h_select,
uint *cntr_lo,
uint *cntr_hi);
int setup_xrm_database (XrmDatabase *db,
char *name[],
int *argc,
char *argv[],
int verbose);
void show_help (char *token);
void split_args (char *args, ...);
int write_hm (void *buff,
uint hist_no,
uint f_bin,
uint n_bins,
uint bpb);
/*
**----------------------------------------------------------------------------*/
void do_dump (char *args) {
/* =======
** Dump out the contents of the histogram buffer
** Args are:
** Number of first bin to dump (dflt = 0)
** Number of bins to dump (dflt = rest of buffer)
** File to receive the data (dflt = standard output)
*/
int i, j, k;
time_t time_now;
uint n_items, f_bin, n_bins;
uint total = 0;
char *p_p1, *p_p2, *p_p3;
char recd[256];
FILE *lun;
uchar *p_byte;
usint *p_word;
uint *p_long;
if (Hm_buff_used == 0) {
printf ("There is nothing available to dump!\n");
return;
}
n_items = Hm_buff_used/Bytes_per_bin;
split_args (args, &p_p1, &p_p2, &p_p3, NULL);
if (p_p1 == NULL) p_p1 = "0";
if ((sscanf (p_p1, "%u", &f_bin) != 1) ||
(f_bin >= n_items)) {
printf ("<1st-bin> is invalid: \"%s\"\n", p_p1);
return;
}
if (p_p2 == NULL) {
n_bins = n_items - f_bin;
}else {
if ((sscanf (p_p2, "%u", &n_bins) != 1) ||
(n_bins > n_items) ||
((n_bins + f_bin) > n_items)) {
printf ("<#-bins> is invalid: \"%s\"\n", p_p2);
n_bins = n_items - f_bin;
printf ("It has been set to %d\n", n_bins);
}
}
if (p_p3 == NULL) {
printf (" Dumping histogram memory buffer ...\n");
lun = stdout;
}else {
printf (" Opening file %s to receive the memory dump ...\n", p_p3);
lun = fopen (p_p3, "w");
if (lun == NULL) {
printf (" ... failed to open file. No dump made!\n");
return;
}
time_now = time (NULL);
fprintf (lun, "! Histogram Memory Dump of %s at %s",
Rmt_host, asctime (localtime (&time_now)));
fprintf (lun, "! =====================\n");
}
fprintf (lun, "First-bin: %5u\n", f_bin);
fprintf (lun, "Number-of-bins: %5u\n", n_bins);
p_byte = (uchar *) Hm_buff_addr;
p_word = (usint *) Hm_buff_addr;
p_long = (uint *) Hm_buff_addr;
for (i = 0; i < n_bins; i += 10) {
k = 0;
for (j = 0; j < 10; j++) {
if ((i + j) >= n_bins) break;
switch (Bytes_per_bin) {
case 1: k += sprintf (&recd[k], "%5d", p_byte[f_bin+i+j]);
total += p_byte[f_bin+i+j];
break;
case 2: k += sprintf (&recd[k], "%6d", p_word[f_bin+i+j]);
total += p_word[f_bin+i+j];
break;
case 4: k += sprintf (&recd[k], "%7d", p_long[f_bin+i+j]);
total += p_long[f_bin+i+j];
}
}
if (j > 0) fprintf (lun, "%6d: %s\n", f_bin+i, recd);
}
if (lun == stdout) printf ("\n");
fprintf (lun, "Total: %u\n", total);
if (lun != stdout) {
fclose (lun);
chmod (p_p3, 0644);
printf (" ... dump completed.\n");
}
}
/*
**----------------------------------------------------------------------------*/
void do_load (char *args, int dbg_mode) {
/* =======
** Load the contents of the histogram buffer from a file
** Args are:
** File to read to get the data (dflt = standard input)
*/
int i, j, binnum, status;
uint bytes_needed, f_bin, n_bins, value;
uint total = 0;
char *p_p1, *pBinnum, *tok;
char recd[256];
FILE *lun;
uchar *p_byte;
usint *p_word;
uint *p_long;
if (Rw_skt == 0) {
Rw_skt = openConnectionGbl (Rmt_host, &Rmt_port, &Pkt_size, dbg_mode,
&Rply_buff, Verbose);
if (Rw_skt == 0) FailInet ("\ndo_load/openConnectionGbl error.");
}
split_args (args, &p_p1, NULL);
if (p_p1 == NULL) {
printf (" Loading histogram memory from standard input ...\n");
lun = stdin;
}else {
printf (" Reading histogram memory data from file %s ...\n", p_p1);
lun = fopen (p_p1, "r");
if (lun == NULL) {
printf (" ... failed to open file. No load done!\n");
return;
}
}
get_recd (lun, recd, sizeof (recd)); /* Get first non-comment record */
i = sscanf (recd, "First-bin: %i%n", &f_bin, &j);
if ((i != 1) || (j != strlen (recd))) {
printf (" ... First-bin record not found. No load done!\n");
if (lun != stdin) fclose (lun);
return;
}
get_recd (lun, recd, sizeof (recd)); /* Get second non-comment record */
i = sscanf (recd, "Number-of-bins: %i%n", &n_bins, &j);
if ((i != 1) || (j != strlen (recd))) {
printf (" ... Number-of-bins record not found. No load done!\n");
if (lun != stdin) fclose (lun);
return;
}
printf ("First-bin: %5u\n", f_bin);
printf ("Number-of-bins: %5u\n", n_bins);
bytes_needed = n_bins * Bytes_per_bin;
if (bytes_needed > Hm_buff_size) { /* Expand buffer space? */
Hm_buff_addr = realloc (Hm_buff_addr, bytes_needed); /* Yes */
if (Hm_buff_addr != NULL) {
Hm_buff_size = bytes_needed;
}else {
printf ("Error getting memory buffer for file data. No load done!\n");
if (lun != stdin) fclose (lun);
return;
}
}
Hm_buff_used = bytes_needed;
p_byte = (uchar *) Hm_buff_addr;
p_word = (usint *) Hm_buff_addr;
p_long = (uint *) Hm_buff_addr;
for (i = 0; i < n_bins; i += 10) {
status = get_recd (lun, recd, sizeof (recd)); /* Get another record */
if (!status) {
printf ("Error getting data from file at record %d! No load done!\n",
(i+10)/10);
if (lun != stdin) fclose (lun);
return;
}
pBinnum = strtok (recd, ":");
if ((pBinnum == NULL) ||
(sscanf (pBinnum, "%i", &binnum) != 1) ||
(binnum != (i + f_bin))) {
printf ("Bin number wrong at record %d! No load done!\n", (i+10)/10);
if (lun != stdin) fclose (lun);
return;
}
for (j = 0; j < 10; j++) {
if ((i + j) >= n_bins) break;
tok = strtok (NULL, " ");
if ((tok == NULL) || (sscanf (tok , "%u", &value) != 1)) {
printf ("Bad data value on record %d! No load done!\n", (i+10)/10);
if (lun != stdin) fclose (lun);
return;
}
switch (Bytes_per_bin) {
case 1: p_byte[i+j] = value; total += p_byte[i+j]; break;
case 2: p_word[i+j] = value; total += p_word[i+j]; break;
case 4: p_long[i+j] = value; total += p_long[i+j];
}
}
}
get_recd (lun, recd, sizeof (recd)); /* Get last non-comment record */
i = sscanf (recd, "Total: %i%n", &value, &j);
if ((i != 1) || (j != strlen (recd))) {
printf (" ... \"Total\" record not found. No load done!\n");
if (lun != stdin) fclose (lun);
return;
}
if (value != total) {
printf (" ... the \"Total\" record is inconsistent. No load done!\n");
printf (" Total of bins = %6u\n"
" Total on \"Total\" record = %6u\n", total, value);
if (lun != stdin) fclose (lun);
return;
}
printf (" Sending the data ...");
status = write_hm (Hm_buff_addr, -1, f_bin, n_bins, Bytes_per_bin);
if (lun != stdin) fclose (lun);
if (status) printf (" load completed.\n");
}
/*
**----------------------------------------------------------------------------*/
void do_plot (uint first, uint n_bins, uint bytes_per_bin, uint total) {
/* =======
** Make a plot of the data.
*/
int i;
char total_txt[21];
#ifdef LINUX
char dev[] = "/XSERV";
#else
char dev[] = "/XW";
#endif
char xlab[] = "Bins";
char ylab[] = "Counts";
float xlo, xhi, yhi;
float *x;
float *y;
uchar *p_byte;
usint *p_word;
uint *p_long;
if ((n_bins <= 0) || (total == 0)) {
printf ("Nothing to plot!\n");
return;
}
x = (float *) malloc ((n_bins + 1) * sizeof (float));
if (x == NULL) {
printf ("Cannot get plot memory for x-array\n");
return;
}
y = (float *) malloc (n_bins * sizeof (float));
if (y == NULL) {
printf ("Cannot get plot memory for y-array\n");
return;
}
sprintf (total_txt, "Bin Total = %8d", total);
p_byte = (uchar *) Hm_buff_addr;
p_word = (usint *) Hm_buff_addr;
p_long = (uint *) Hm_buff_addr;
if (PGPLOT_started == 0) {
cpgbeg (0, dev, 1, 1);
/* - - - - - - - - - - - - - - - - - - - - - -
** Set black on white (hopefully)
*/
cpgscr (0, 0.79, 0.67, 0.57);
cpgscr (1, 0.0, 0.0, 0.0);
cpgask (0);
PGPLOT_started = 1;
}
xlo = (float) first;
xhi = (float) first + n_bins + 1;
yhi = 10.0;
switch (bytes_per_bin) {
case 1:
for (i = 0; i < n_bins; i++) {
x[i] = first + i;
y[i] = p_byte[i];
if (y[i] > yhi) yhi = y[i];
}
break;
case 2:
for (i = 0; i < n_bins; i++) {
x[i] = first + i;
y[i] = p_word[i];
if (y[i] > yhi) yhi = y[i];
}
break;
case 4:
for (i = 0; i < n_bins; i++) {
x[i] = first + i;
y[i] = p_long[i];
if (y[i] > yhi) yhi = y[i];
}
break;
}
x[n_bins] = first + n_bins;
yhi = cpgrnd (yhi, &i);
cpgenv (xlo, xhi, 0.0, yhi, 0, 0);
cpglab (xlab, ylab, total_txt);
cpgbin (n_bins, x, y, False);
cpgmove (x[n_bins], y[n_bins-1]); cpgdraw (x[n_bins], 0.0);
free (x);
free (y);
}
/*
**----------------------------------------------------------------------------*/
void do_project (char *args, int dbg_mode) {
/* ==========
** Generate a projected plot of a 2-dim hist (e.g. of TOF array of cntrs)
** Args are:
** Number of first histogram
** Number of histograms
** Number of first bin
** Number of bins
** Axis ('X' = x-axis, 'Y' = y-axis)
** x-dim
** Default is to project everything onto x-axis
*/
char *p_p1, *p_p2, *p_p3, *p_p4, *p_p5, *p_p6, *p_p7;
int i, status, axis;
uint f_hist, n_hists, f_bin, n_bins;
uint x_dim, h_slct, eff_nbins, eff_nhists;
uint nbins_to_read, bytes_needed, total, cntr_lo, cntr_hi;
uchar *p_byte;
usint *p_word;
uint *p_long;
if (Rw_skt == 0) {
Rw_skt = openConnectionGbl (Rmt_host, &Rmt_port, &Pkt_size, dbg_mode,
&Rply_buff, Verbose);
if (Rw_skt == 0) FailInet ("\ndo_project/openConnectionGbl error.");
}
split_args (args, &p_p1, &p_p2, &p_p3, &p_p4, /* Get pntrs to */
&p_p5, &p_p6, &p_p7, NULL); /* the 7 args */
if (p_p6 == NULL) {
x_dim = 0;
}else {
if ((sscanf (p_p6, "%u", &x_dim) != 1) ||
(x_dim > Hm_nbins) ||
((x_dim != 0) && ((Hm_nbins % x_dim) != 0))) {
printf ("<x-dim> is invalid: \"%s\"\n", p_p6);
printf ("<x-dim> must be an exact divisor of the number of bins "
"per histogram, %d\n", Hm_nbins);
return;
}
}
eff_nbins = (x_dim == 0) ? Hm_nbins : x_dim;
eff_nhists = (x_dim == 0) ? N_hists : (Hm_nbins/x_dim);
if (p_p1 == NULL) p_p1 = "0";
if ((sscanf (p_p1, "%u", &f_hist) != 1) ||
(f_hist >= eff_nhists)) {
printf ("<1st-hist> is invalid: \"%s\"\n", p_p1);
printf ("It must be an integer in the range 0 to %d\n", (eff_nhists - 1));
return;
}
if (p_p2 == NULL) {
n_hists = eff_nhists - f_hist;
}else {
if ((sscanf (p_p2, "%u", &n_hists) != 1) ||
(n_hists == 0) ||
(n_hists > eff_nhists) ||
((n_hists + f_hist) > eff_nhists)) {
printf ("<#-hists> is invalid: \"%s\"\n", p_p2);
printf ("It must be an integer in the range 1 to %d\n",
(eff_nhists - f_hist));
return;
}
}
if (p_p3 == NULL) p_p3 = "0";
if ((sscanf (p_p3, "%u", &f_bin) != 1) ||
(f_bin >= eff_nbins)) {
printf ("<1st-bin> is invalid: \"%s\"\n", p_p3);
printf ("It must be an integer in the range 0 to %d\n",
(eff_nbins - 1));
return;
}
if (p_p4 == NULL) {
n_bins = eff_nbins - f_bin;
}else {
if ((sscanf (p_p4, "%u", &n_bins) != 1) ||
(n_bins > eff_nbins) ||
((n_bins + f_bin) > eff_nbins)) {
printf ("<#-bins> is invalid: \"%s\"\n", p_p4);
printf ("It must be an integer in the range 1 to %d\n",
(eff_nbins - f_bin));
return;
}
}
if (p_p5 == NULL) {
axis = 0;
}else {
if (strcmp ("x", p_p5) == 0) {
axis = 0;
}else if (strcmp ("y", p_p5) == 0) {
axis = 1;
}else if (sscanf (p_p4, "%u", &axis) == 1) {
if (axis != 0) axis = 1;
}else {
printf ("<axis> is invalid: \"%s\"\n", p_p5);
printf ("It should be \"x\" or \"y\"\n");
return;
}
}
if (p_p7 == NULL) {
h_slct = 0;
}else {
if ((sscanf (p_p7, "%u", &h_slct) != 1) ||
(h_slct > N_hists)) {
printf ("<hist-#> is invalid: \"%s\"\n", p_p7);
printf ("It must be an integer in the range 1 to %d\n", (N_hists - 1));
return;
}
}
printf ("\n Read Projected Region of 2-dimensional histogram ...\n"
" First histogram = %5u\n"
" Number of histograms = %5u\n"
" First bin = %5u\n"
" Number of bins = %5u\n",
f_hist, n_hists, f_bin, n_bins, axis);
if (axis == 0) printf (" Axis = X\n");
if (axis != 0) printf (" Axis = Y\n");
if (x_dim != 0) printf (" x-dimension = %5u\n", x_dim);
/*
** Allocate buffer space for holding the data. The space needed
** depends on whether it is an x- or y-projection.
*/
nbins_to_read = (axis == 0) ? n_bins : n_hists;
bytes_needed = nbins_to_read * sizeof (uint);
if (bytes_needed > Hm_buff_size) { /* Expand buffer space? */
Hm_buff_addr = realloc (Hm_buff_addr, bytes_needed); /* Yes */
if (Hm_buff_addr != NULL) {
Hm_buff_size = bytes_needed;
}else {
printf ("SinqHM_Client -- "
"error getting memory buffer for histogram data.\n");
exit (EXIT_FAILURE);
}
}
Hm_buff_used = bytes_needed;
status = read_project (Hm_buff_addr, Hm_buff_size,
f_bin, n_bins, f_hist, n_hists, axis, x_dim, h_slct,
&cntr_lo, &cntr_hi);
if (status == EXIT_SUCCESS) {
total = 0;
switch (Bytes_per_bin) {
case 1:
p_byte = (uchar *) Hm_buff_addr;
for (i = 0; i < nbins_to_read; i++) total += p_byte[i];
break;
case 2:
p_word = (usint *) Hm_buff_addr;
for (i = 0; i < nbins_to_read; i++) total += p_word[i];
break;
case 4:
p_long = (uint *) Hm_buff_addr;
for (i = 0; i < nbins_to_read; i++) total += p_long[i];
}
printf (" Done! Total contents of bins = %d\n", total);
if (cntr_lo != 0) printf (" Number of underflow events = %u\n", cntr_lo);
if (cntr_hi != 0) printf (" Number of overflow events = %u\n", cntr_hi);
if (axis == 0) {
do_plot (f_bin, n_bins, Bytes_per_bin, total);
}else {
do_plot (f_hist, n_hists, Bytes_per_bin, total);
}
}
}
/*
**----------------------------------------------------------------------------*/
void do_status (int dbg_mode) {
/* =========
** Get and display status of SinqHM_srv
*/
int i, status, secs, mins, hrs, days;
int off_a, off_b, off_c, off_d, off_e, off_f;
int off_g, off_h, off_i, off_j, off_k, off_l;
uint state, nh, nb, bpb, span, ch, bytes_to_come;
char recd[256], *p_buff, *p_nxt;
uint tsi_status, tsi_flags, dt_or_dts, num_bad_ev;
if (Rw_skt == 0) {
Rw_skt = openConnectionGbl (Rmt_host, &Rmt_port, &Pkt_size, dbg_mode,
&Rply_buff, Verbose);
if (Rw_skt == 0) FailInet ("\ndo_status/openConnectionGbl error.");
}
printf ("\n Getting histogram memory identification ...\n");
/*
** Send the ident request message first
*/
Req_buff.bigend = htonl (0x12345678);
Req_buff.cmnd = htonl (SQHM_IDENT);
status = send (Rw_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
if (status == -1) FailInet ("do_status -- R/W-Socket send error\n");
if (status != sizeof (Req_buff)) {
printf ("SinqHM_Client -- wrong number of bytes sent: %d", status);
exit (EXIT_FAILURE);
}
/*
** Now get the server's ident message.
*/
status = recv (Rw_skt, (char *) &Rply_buff, sizeof (Rply_buff), 0);
if (status == -1) {
FailInet ("do_status -- R/W-Socket recv error\n");
exit (EXIT_FAILURE);
}else if (status != sizeof (Rply_buff)) {
printf ("do_status -- Cnct-Socket recv error - ");
printf ("unexpected byte count: %d.\n", status);
exit (EXIT_FAILURE);
}
if (ntohl (Rply_buff.bigend) != 0x12345678) {
printf (
"SinqHM_Client -- big-endian/little-endian problem!\n"
" Buffer received in non-network byte order!\n");
exit (EXIT_FAILURE);
}else if (ntohl (Rply_buff.status) == KER__BAD_VALUE) {
printf (" ... identification request not supported\n");
}else if (ntohl (Rply_buff.status) != KER__SUCCESS) {
printf ("SinqHM_Client -- Bad status from Ident Request: %d.\n",
ntohl (Rply_buff.status));
printf (" \"%s\"\n", Rply_buff.u.message);
exit (EXIT_FAILURE);
}else {
/*
** Get the rest of the response
*/
bytes_to_come = ntohl (Rply_buff.u.ident.n_extra_bytes);
p_buff = calloc (bytes_to_come, 1);
if (p_buff == NULL) {
printf ("Could not get buffer space for ident information\n");
exit (EXIT_FAILURE);
}
p_nxt = p_buff;
while (bytes_to_come > 0) {
i = (bytes_to_come > Pkt_size) ? Pkt_size : bytes_to_come;
status = recv (Rw_skt, p_nxt, i, 0);
Rw_bytes_got += status;
if (status == -1) FailInet ("do_status -- R/W-Socket data recv error\n");
bytes_to_come -= status;
p_nxt += status;
}
/*
** Extract and print the information
*/
off_a = ntohs (Rply_buff.u.ident.offset_vxWorks_ident);
off_b = ntohs (Rply_buff.u.ident.offset_vxWorks_date);
off_c = ntohs (Rply_buff.u.ident.offset_instr);
off_d = ntohs (Rply_buff.u.ident.offset_def_ident);
off_e = ntohs (Rply_buff.u.ident.offset_sinqhm_main_ident);
off_f = ntohs (Rply_buff.u.ident.offset_sinqhm_main_date);
off_g = ntohs (Rply_buff.u.ident.offset_sinqhm_server_ident);
off_h = ntohs (Rply_buff.u.ident.offset_sinqhm_server_date);
off_i = ntohs (Rply_buff.u.ident.offset_sinqhm_filler_ident);
off_j = ntohs (Rply_buff.u.ident.offset_sinqhm_filler_date);
off_k = ntohs (Rply_buff.u.ident.offset_sinqhm_routines_ident);
off_l = ntohs (Rply_buff.u.ident.offset_sinqhm_routines_date);
i = strlen (&p_buff[off_b]) + 1;
StrEdit (&p_buff[off_b], &p_buff[off_b], "compress trim", &i);
i = strlen (&p_buff[off_f]) + 1;
StrEdit (&p_buff[off_f], &p_buff[off_f], "compress trim", &i);
i = strlen (&p_buff[off_h]) + 1;
StrEdit (&p_buff[off_h], &p_buff[off_h], "compress trim", &i);
i = strlen (&p_buff[off_j]) + 1;
StrEdit (&p_buff[off_j], &p_buff[off_j], "compress trim", &i);
i = strlen (&p_buff[off_l]) + 1;
StrEdit (&p_buff[off_l], &p_buff[off_l], "compress trim", &i);
printf (" Instrument = %s, SinqHM Protocol Identifier = %s\n",
&p_buff[off_c], &p_buff[off_d]);
printf (" SinqHM_srv_main Identifier %s compiled on %s\n",
&p_buff[off_e], &p_buff[off_f]);
printf (" SinqHM_srv_server Identifier %s compiled on %s\n",
&p_buff[off_g], &p_buff[off_h]);
printf (" SinqHM_srv_filler Identifier %s compiled on %s\n",
&p_buff[off_i], &p_buff[off_j]);
printf (" SinqHM_srv_routines Identifier %s compiled on %s\n",
&p_buff[off_k], &p_buff[off_l]);
printf (" vxWorks Version %s created on %s\n", &p_buff[off_a],
&p_buff[off_b]);
print_uptime (stdout, " Up-time = ", ntohl (Rply_buff.u.ident.up_time),
"\n");
free (p_buff);
}
/*----------------------------------------------------------------------------*/
printf ("\n Getting histogram memory status ...\n");
/*
** Send the request message first
*/
Req_buff.bigend = htonl (0x12345678);
Req_buff.cmnd = htonl (SQHM_STATUS);
status = send (Rw_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
if (status == -1) FailInet ("do_status -- R/W-Socket send error\n");
if (status != sizeof (Req_buff)) {
printf ("SinqHM_Client -- wrong number of bytes sent: %d", status);
exit (EXIT_FAILURE);
}
/*
** Now get the server's status message.
*/
status = recv (Rw_skt, (char *) &Rply_buff, sizeof (Rply_buff), 0);
if (status == -1) {
FailInet ("do_status -- R/W-Socket recv error\n");
exit (EXIT_FAILURE);
}else if (status != sizeof (Rply_buff)) {
printf ("do_status -- Cnct-Socket recv error - ");
printf ("unexpected byte count: %d.\n", status);
exit (EXIT_FAILURE);
}
if (ntohl (Rply_buff.bigend) != 0x12345678) {
printf (
"SinqHM_Client -- big-endian/little-endian problem!\n"
" Buffer received in non-network byte order!\n");
exit (EXIT_FAILURE);
}else if (ntohl (Rply_buff.status) != KER__SUCCESS) {
printf ("SinqHM_Client -- Bad status from Status Request: %d.\n",
ntohl (Rply_buff.status));
printf (" \"%s\"\n", Rply_buff.u.message);
exit (EXIT_FAILURE);
}else {
/*
** Display the status obtained.
*/
printf (" Maximum number of connections = %6d\n",
Rply_buff.u.status.max_srvrs);
printf (" Maximum number of histograms = %6d\n",
ntohl (Rply_buff.u.status.max_n_hists));
printf (" Maximum number of bins per histogram = %6d\n",
ntohl (Rply_buff.u.status.max_num_bins));
if (Rply_buff.u.status.cfg_state == 0) {
printf (" Space available for histograms = %6d\n\n",
ntohl (Rply_buff.u.status.max_block));
}else {
printf (" Free buffer space available = %6d\n\n",
ntohl (Rply_buff.u.status.max_block));
}
if (Rply_buff.u.status.cfg_state == 0) {
printf (" SINQHM has not yet been configured.\n");
}else {
state = ntohl (Rply_buff.u.status.cfg_state);
nh = ntohs (Rply_buff.u.status.n_hists);
ch = ntohs (Rply_buff.u.status.curr_hist);
nb = ntohl (Rply_buff.u.status.num_bins);
bpb = Rply_buff.u.status.bytes_per_bin;
span = Rply_buff.u.status.compress;
if ((Hm_mode & (~SQHM__SUB_MODE_MSK)) !=
(state & (~SQHM__SUB_MODE_MSK)))
new_config_quit ("hm_mode/cfg_state");
if (N_hists != nh) new_config_quit ("n_hists");
if (Hm_nbins != nb) new_config_quit ("num_bins");
if (Bytes_per_bin != bpb) new_config_quit ("bytes_per_bin");
print_HM_mode (state, 10);
if (nh != 1) printf (" Number of histograms = %6d\n", nh);
if (ch != 0) printf (" Current histogram = %6d\n", ch);
printf (" Number of bins per histogram = %6d\n", nb);
if (nh > 1) printf (" Total number of bins = %6d\n", nh * nb);
if (span > 1) printf (" Bin span = %6d\n", span);
printf (" Number of bytes per bin = %6d\n", bpb);
printf (" Number of active connections = %6d\n",
Rply_buff.u.status.act_srvrs);
if (Rply_buff.u.status.daq_now == 0) {
printf (" Data acquisition is active\n");
}else {
printf (" Data acquisition is not active\n");
}
tsi_status = ntohs (Rply_buff.u.status.tsi_status);
tsi_flags = ntohs (Rply_buff.u.status.flags);
dt_or_dts = ntohl (Rply_buff.u.status.dt_or_dts.both);
num_bad_ev = ntohl (Rply_buff.u.status.num_bad_events);
if (dt_or_dts != 0) {
if ((Hm_mode & (~SQHM__SUB_MODE_MSK)) == SQHM__TOF) {
printf (" Delay-Time-to-Start = %6u\n", dt_or_dts);
}else {
printf (" Dead-Time = %6u\n", dt_or_dts);
}
}
if (num_bad_ev != 0) {
printf (" Number-of-Bad-Events = %u\n", num_bad_ev);
}
if ((tsi_status != 0) || (tsi_flags != 0)) {
printf (" TSI Status Info = 0x%04x\n", tsi_status);
printf (" TSI Flags = 0x%04x", tsi_flags);
if ((tsi_flags & STATUS_FLAGS__PF) != 0) printf (" PF");
if ((tsi_flags & STATUS_FLAGS__SWC) != 0) printf (" SWC");
if ((tsi_flags & STATUS_FLAGS__NRL) != 0) printf (" NRL");
if ((tsi_flags & STATUS_FLAGS__DAQ) != 0) printf (" DAQ");
if ((tsi_flags & STATUS_FLAGS__SYNC3) != 0) printf (" SYNC3");
if ((tsi_flags & STATUS_FLAGS__SYNC2) != 0) printf (" SYNC2");
if ((tsi_flags & STATUS_FLAGS__SYNC1) != 0) printf (" SYNC1");
if ((tsi_flags & STATUS_FLAGS__SYNC0) != 0) printf (" SYNC0");
if ((tsi_flags & STATUS_FLAGS__UD) != 0) printf (" UD");
if ((tsi_flags & STATUS_FLAGS__GU) != 0) printf (" GU");
printf ("\n");
}
}
}
}
/*
**----------------------------------------------------------------------------*/
void do_1d (char *args, int dbg_mode) {
/* =====
** Generate a 1-dim plot
** Args are:
** Number of first bin (dflt = 0)
** Number of bins (dflt = rest of histogram)
** Number of histogram (dflt = -1)
** Default is to plot everything.
*/
int i, status;
uint f_bin, n_bins, hist_num;
uint cntr_lo, cntr_hi;
uint total;
char *p_p1, *p_p2, *p_p3;
unsigned char *p_byte;
unsigned short int *p_word;
unsigned int *p_long;
if (Rw_skt == 0) {
Rw_skt = openConnectionGbl (Rmt_host, &Rmt_port, &Pkt_size, dbg_mode,
&Rply_buff, Verbose);
if (Rw_skt == 0) FailInet ("\ndo_1d/openConnectionGbl error.");
}
split_args (args, &p_p1, &p_p2, &p_p3, NULL);
if (p_p1 == NULL) p_p1 = "0";
if (sscanf (p_p1, "%u", &f_bin) != 1) {
printf ("<1st-bin> is invalid: \"%s\"\n", p_p1);
return;
}
if (p_p3 == NULL) p_p3 = "-1";
if ((sscanf (p_p3, "%u", &hist_num) != 1) ||
((hist_num != -1) && (hist_num >= N_hists))) {
printf ("<hist-#> is invalid: \"%s\"\n", p_p3);
printf ("There are %d histograms defined.\n", N_hists);
return;
}
if (((hist_num != -1) && (f_bin >= Hm_nbins)) ||
(f_bin >= (N_hists * Hm_nbins))) {
printf ("<1st-bin> is invalid: \"%s\"\n", p_p1);
printf ("The number of bins is %d\n",
(hist_num == -1) ? (N_hists * Hm_nbins) : Hm_nbins);
return;
}
if (p_p2 != NULL) {
if ((sscanf (p_p2, "%d", &n_bins) != 1) ||
((hist_num != -1) && ((f_bin + n_bins) > Hm_nbins)) ||
((f_bin + n_bins) >= (N_hists * Hm_nbins))) {
printf ("<#-bins> is invalid: \"%s\"\n", p_p2);
n_bins = (hist_num == -1) ? (N_hists * Hm_nbins) : Hm_nbins;
n_bins = n_bins - f_bin;
printf ("The value has been set to %d.\n", n_bins);
}
}else {
n_bins = (hist_num == -1) ? (N_hists * Hm_nbins) : Hm_nbins;
n_bins = n_bins - f_bin;
}
printf (" Read histogram memory ...\n"
" First bin = %5d\n"
" Number of bins = %5d\n"
" Histogram number = %5d\n", f_bin, n_bins, hist_num);
/*
** Allocate buffer space for holding the data.
*/
if ((n_bins * Bytes_per_bin) > Hm_buff_size) { /* Expand buffer space? */
Hm_buff_addr = realloc (Hm_buff_addr, (n_bins * Bytes_per_bin)); /* Yes */
if (Hm_buff_addr != NULL) {
Hm_buff_size = n_bins * Bytes_per_bin;
}else {
printf ("SinqHM_Client -- "
"error getting memory buffer for histogram data.\n");
exit (EXIT_FAILURE);
}
}
Hm_buff_used = n_bins * Bytes_per_bin;
status = read_hm (Hm_buff_addr, Hm_buff_size,
f_bin, n_bins, hist_num, &cntr_lo, &cntr_hi);
if (status == EXIT_SUCCESS) {
total = 0;
switch (Bytes_per_bin) {
case 1:
p_byte = (uchar *) Hm_buff_addr;
for (i=0; i < n_bins; i++) total += p_byte[i];
break;
case 2:
p_word = (usint *) Hm_buff_addr;
for (i=0; i < n_bins; i++) total += p_word[i];
break;
case 4:
p_long = (uint *) Hm_buff_addr;
for (i=0; i < n_bins; i++) total += p_long[i];
break;
}
printf (" Done! Total contents of bins = %d\n", total);
if (cntr_lo != 0) printf (" Number of underflow events = %u\n", cntr_lo);
if (cntr_hi != 0) printf (" Number of overflow events = %u\n", cntr_hi);
do_plot (f_bin, n_bins, Bytes_per_bin, total);
}
}
/*
**----------------------------------------------------------------------------*/
void do_2d (char *args, int dbg_mode) {
/* =====
** Generate a 2-dim plot (e.g. of TOF array of counters
** Args are:
** Number of first histogram
** Number of histograms
** Number of first bin
** Number of bins
** Default is to plot everything.
*/
char *p_p1, *p_p2, *p_p3, *p_p4;
int i, status;
uint f_hist, n_hists, f_bin, n_bins;
uint bytes_needed, total, cntr_lo, cntr_hi;
uchar *p_byte;
usint *p_word;
uint *p_long;
if (Rw_skt == 0) {
Rw_skt = openConnectionGbl (Rmt_host, &Rmt_port, &Pkt_size, dbg_mode,
&Rply_buff, Verbose);
if (Rw_skt == 0) FailInet ("\ndo_2d/openConnectionGbl error.");
}
split_args (args, &p_p1, &p_p2, &p_p3, &p_p4, NULL); /* Get pointers to
** the 4 args */
if (p_p1 == NULL) p_p1 = "0";
if ((sscanf (p_p1, "%u", &f_hist) != 1) ||
(f_hist >= N_hists)) {
printf ("<1st-hist> is invalid: \"%s\"\n", p_p1);
printf ("There are %d histograms defined.\n", N_hists);
return;
}
if (p_p2 == NULL) {
n_hists = N_hists - f_hist;
}else {
if ((sscanf (p_p2, "%u", &n_hists) != 1) ||
(n_hists > N_hists) ||
((n_hists + f_hist) > N_hists)) {
printf ("<#-hists> is invalid: \"%s\"\n", p_p2);
printf ("There are %d histograms defined.\n", N_hists);
return;
}
}
if (p_p3 == NULL) p_p3 = "0";
if ((sscanf (p_p3, "%u", &f_bin) != 1) ||
(f_bin >= Hm_nbins)) {
printf ("<1st-bin> is invalid: \"%s\"\n", p_p3);
printf ("The number of bins is %d\n", Hm_nbins);
return;
}
if (p_p4 == NULL) {
n_bins = Hm_nbins - f_bin;
}else {
if ((sscanf (p_p4, "%u", &n_bins) != 1) ||
(n_bins > Hm_nbins) ||
((n_bins + f_bin) > Hm_nbins)) {
printf ("<#-bins> is invalid: \"%s\"\n", p_p4);
printf ("The number of bins is %d\n", Hm_nbins);
return;
}
}
printf ("\n Read 2-dimensional histogram memory ...\n"
" First histogram = %5u\n"
" Number of histograms = %5u\n"
" First bin = %5u\n"
" Number of bins = %5u\n",
f_hist, n_hists, f_bin, n_bins);
/*
** Allocate buffer space for holding the data. Note that the
** data in the Hist Mem is stored as a 1-dim array with
** the bins of each histogram contiguous. It is usually
** more efficient (at least, it is easier to program) to
** transfer over complete histograms if we need to pick out
** a sub-range of bins.
*/
bytes_needed = n_hists * Hm_nbins * Bytes_per_bin;
if (bytes_needed > Hm_buff_size) { /* Expand buffer space? */
Hm_buff_addr = realloc (Hm_buff_addr, bytes_needed); /* Yes */
if (Hm_buff_addr != NULL) {
Hm_buff_size = bytes_needed;
}else {
printf ("SinqHM_Client -- "
"error getting memory buffer for histogram data.\n");
exit (EXIT_FAILURE);
}
}
Hm_buff_used = bytes_needed;
status = read_hm (Hm_buff_addr, Hm_buff_size,
(f_hist * Hm_nbins), (n_hists * Hm_nbins), -1,
&cntr_lo, &cntr_hi);
if (status == EXIT_SUCCESS) {
total = 0;
switch (Bytes_per_bin) {
case 1:
p_byte = (uchar *) Hm_buff_addr;
for (i=0; i<(n_hists * Hm_nbins); i++) total += p_byte[i];
break;
case 2:
p_word = (usint *) Hm_buff_addr;
for (i=0; i<(n_hists * Hm_nbins); i++) total += p_word[i];
break;
case 4:
p_long = (uint *) Hm_buff_addr;
for (i=0; i<(n_hists * Hm_nbins); i++) total += p_long[i];
}
printf (" Done! Total contents of bins = %d\n", total);
if (cntr_lo != 0) printf (" Number of underflow events = %u\n", cntr_lo);
if (cntr_hi != 0) printf (" Number of overflow events = %u\n", cntr_hi);
do_2d_plot (f_hist, n_hists, f_bin, n_bins, Bytes_per_bin, total);
}
}
/*
**----------------------------------------------------------------------------*/
void do_2d_plot (
/* ==========
** Make a 2-dimensional plot of the data.
*/
uint f_hist, uint n_hists, uint f_bin, uint n_bins,
uint bytes_per_bin, uint total) {
int i, t_bins, ix1, ix2, iy1, iy2, ioff;
int nx = 1;
int ny = 1;
char total_txt[21];
#ifdef LINUX
char dev[] = "/XSERV";
#else
char dev[] = "/XW";
#endif
char xlab[] = "Bins";
char ylab[] = "Counts";
float xlo, xhi, yhi, bias;
float *data;
float *x, *ylims;
uchar *p_byte;
usint *p_word;
uint *p_long;
if ((n_hists == 0) || (n_bins == 0) || (total == 0)) {
printf ("Nothing to plot!\n");
return;
}
p_byte = (uchar *) Hm_buff_addr;
p_word = (usint *) Hm_buff_addr;
p_long = (uint *) Hm_buff_addr;
t_bins = n_hists * Hm_nbins;
data = (float *) malloc (t_bins * sizeof (float));
if (data == NULL) {
printf ("Cannot get plot memory for 2-dim array\n");
return;
}
x = (float *) malloc ((n_bins + 1) * sizeof (float));
if (x == NULL) {
printf ("Cannot get plot memory for x-array\n");
return;
}
ylims = (float *) malloc ((n_bins + 1) * sizeof (float));
if (x == NULL) {
printf ("Cannot get workspace memory for 2-dim plot\n");
return;
}
switch (bytes_per_bin) {
case 1:
for (i = 0; i < t_bins; i++) data[i] = p_byte[i]; break;
case 2:
for (i = 0; i < t_bins; i++) data[i] = p_word[i]; break;
case 4:
for (i = 0; i < t_bins; i++) data[i] = p_long[i]; break;
}
yhi = 10.0;
for (i = 0; i < t_bins; i++) if (data[i] > yhi) yhi = data[i];
yhi = yhi * 1.3;
yhi = cpgrnd (yhi, &i);
ioff = 1;
for (i = 0; i <= n_bins; i++) x[i] = (float) (f_bin + i);
xlo = (float) f_bin;
xhi = (float) f_bin + n_bins + 1 + (n_hists * ioff);
ix1 = 1;
ix2 = n_hists;
iy1 = f_bin + 1;
iy2 = f_bin + n_bins;
bias = yhi * 0.0001;
sprintf (total_txt, "Bin Total = %8d", total);
if (PGPLOT_started == 0) {
cpgbeg (0, dev, 1, 1);
/* - - - - - - - - - - - - - - - - - - - - - -
** Set black on white (hopefully)
*/
cpgscr (0, 0.79, 0.67, 0.57);
cpgscr (1, 0.0, 0.0, 0.0);
cpgask (0);
PGPLOT_started = 1;
}
cpgenv (xlo, xhi, 0.0, yhi, 0, 0);
cpglab (xlab, ylab, total_txt);
cpghi2d (data, n_hists, Hm_nbins, ix1, ix2, iy1, iy2, x, ioff,
bias, False, ylims);
free (data);
free (x);
free (ylims);
}
/*
**--------------------------------------------------------------------------*/
void exit_handler () {
/* ============
** We must exit. Tidy up first.
** Close TCP/IP link to front-end.
*/
int status;
/*
** Tell server we're quitting.
*/
if (Rw_skt != 0) {
printf ("Closing connection to %s ...\n", Rmt_host);
Req_buff.bigend = htonl (0x12345678);
Req_buff.cmnd = htonl (SQHM_CLOSE);
status = send (Rw_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
Rw_bytes_put += status;
if (status == -1) FailInet ("exit_handler -- R/W-Socket send error\n");
if (status != sizeof (Req_buff)) {
printf ("EXIT_HANDLER -- wrong number of bytes sent: %d", status);
exit (EXIT_FAILURE);
}
status = close (Rw_skt);
Rw_skt = 0;
if (status != 0) FailInet ("exit_handler -- R/W-Socket close error\n");
}
}
/*
**--------------------------------------------------------------------------*/
void gen_data (char *args) {
/* ========
** Generate sum of 2 Lorenzians.
*/
int i, j, nbins;
char *p_p1, *p_p2, *p_p3, *p_p4, *p_p5, *p_p6;
float p1, p2, p3, p4, p5, p6;
float ff, fact_1, fact_2;
char *p_byte;
short int *p_word;
int *p_long;
/*
** Allocate buffer space for holding the data.
*/
nbins = Hm_nbins * N_hists;
if ((nbins * Bytes_per_bin) > Hm_buff_size) { /* Expand buffer space? */
Hm_buff_addr = realloc (Hm_buff_addr, (nbins * Bytes_per_bin)); /* Yes */
if (Hm_buff_addr != NULL) {
Hm_buff_size = nbins * Bytes_per_bin;
}else {
printf ("SinqHM_Client -- "
"error getting memory buffer for histogram data.\n");
exit (EXIT_FAILURE);
}
}
Hm_buff_used = nbins * Bytes_per_bin;
/*
** Parse the arguments
*/
split_args (args, &p_p1, &p_p2, &p_p3, &p_p4, &p_p5, &p_p6, NULL);
if ((p_p1 != NULL) && (sscanf (p_p1, "%f", &p1) == 1)) P1 = p1;
if ((p_p2 != NULL) && (sscanf (p_p2, "%f", &p2) == 1)) P2 = p2;
if ((p_p3 != NULL) && (sscanf (p_p3, "%f", &p3) == 1)) P3 = p3;
if ((p_p4 != NULL) && (sscanf (p_p4, "%f", &p4) == 1)) P4 = p4;
if ((p_p5 != NULL) && (sscanf (p_p5, "%f", &p5) == 1)) P5 = p5;
if ((p_p6 != NULL) && (sscanf (p_p6, "%f", &p6) == 1)) P6 = p6;
if (P2 <= 0) P2 = 1000;
if (P5 <= 0) P5 = 1000;
if (P3 <= 0) P3 = ((float) Hm_nbins) * 0.25;
if (P6 <= 0) P6 = ((float) Hm_nbins) * 0.60;
p_byte = (char *) Hm_buff_addr;
p_word = (short int *) Hm_buff_addr;
p_long = (int *) Hm_buff_addr;
for (j = 0; j < N_hists; j++) { /* Calculate sum of 2 Lorenzians */
fact_1 = 0.5 + (float) (j)/(float) (N_hists);
fact_2 = 2.0 - fact_1;
for (i = 0; i < Hm_nbins; i++) {
p1 = ((float) i) - P3; /* First Lorenzian */
p1 = p1 * p1;
p2 = P1/(P2 + p1);
p2 *= fact_1;
p3 = ((float) i) - P6; /* Second Lorenzian */
p3 = p3 * p3;
p4 = P4/(P5 + p3);
p4 *= fact_2;
ff = p2 + p4;
switch (Bytes_per_bin) {
case 1:
*p_byte++ = (char) ff;
break;
case 2:
*p_word++ = (short int) ff;
break;
case 4:
*p_long++ = (int) ff;
break;
}
}
}
}
/*
**--------------------------------------------------------------------------*/
void gen_data_2d (char *args) {
/* ===========
** Same as gen_data, i.e. generate sum of 2
** Lorenzians, but suitable for pseudo 2-dim mode.
** The first arg is the number of sub-histograms.
*/
char *p_nhis, *p_p1, *p_p2, *p_p3, *p_p4, *p_p5, *p_p6;
int i, j, totbins, nhis, nbins;
float p1, p2, p3, p4, p5, p6;
float ff, fact_1, fact_2;
char *p_byte;
short int *p_word;
int *p_long;
/*
** Allocate buffer space for holding the data.
*/
totbins = Hm_nbins * N_hists;
if ((totbins * Bytes_per_bin) > Hm_buff_size) { /* Expand buffer space? */
Hm_buff_addr = realloc (Hm_buff_addr, (totbins * Bytes_per_bin)); /* Yes */
if (Hm_buff_addr != NULL) {
Hm_buff_size = totbins * Bytes_per_bin;
}else {
printf ("SinqHM_Client -- "
"error getting memory buffer for histogram data.\n");
exit (EXIT_FAILURE);
}
}
Hm_buff_used = totbins * Bytes_per_bin;
/*
** Parse the arguments
*/
split_args (args, &p_nhis,
&p_p1, &p_p2, &p_p3, &p_p4, &p_p5, &p_p6, NULL);
if (p_nhis != NULL) {
i = sscanf (p_nhis, "%i", &nhis);
if ((i != 1) || ((totbins % nhis) != 0)) {
if (i != 1) printf ("<#-hists> is invalid. It must be an integer!\n");
if (i == 1) printf ("<#-hists> is invalid. It must be a factor"
" of the total number of bins!\n");
printf ("<#-hists> is \"%s\", total number of bins = %d\n",
p_nhis, totbins);
printf ("<#-hists> set to 1\n");
nhis = 1;
}
}else {
nhis = 1;
}
nbins = totbins/nhis;
if ((p_p1 != NULL) && (sscanf (p_p1, "%f", &p1) == 1)) P1 = p1;
if ((p_p2 != NULL) && (sscanf (p_p2, "%f", &p2) == 1)) P2 = p2;
if ((p_p3 != NULL) && (sscanf (p_p3, "%f", &p3) == 1)) P3 = p3;
if ((p_p4 != NULL) && (sscanf (p_p4, "%f", &p4) == 1)) P4 = p4;
if ((p_p5 != NULL) && (sscanf (p_p5, "%f", &p5) == 1)) P5 = p5;
if ((p_p6 != NULL) && (sscanf (p_p6, "%f", &p6) == 1)) P6 = p6;
if (P2 <= 0) P2 = 1000;
if (P5 <= 0) P5 = 1000;
if (P3 <= 0) P3 = ((float) nbins) * 0.25;
if (P6 <= 0) P6 = ((float) nbins) * 0.60;
p_byte = (char *) Hm_buff_addr;
p_word = (short int *) Hm_buff_addr;
p_long = (int *) Hm_buff_addr;
for (j = 0; j < nhis; j++) { /* Calculate sum of 2 Lorenzians */
fact_1 = 0.5 + (float) (j)/(float) (nhis);
fact_2 = 2.0 - fact_1;
for (i = 0; i < nbins; i++) {
p1 = ((float) i) - P3; /* First Lorenzian */
p1 = p1 * p1;
p2 = P1/(P2 + p1);
p2 *= fact_1;
p3 = ((float) i) - P6; /* Second Lorenzian */
p3 = p3 * p3;
p4 = P4/(P5 + p3);
p4 *= fact_2;
ff = p2 + p4;
switch (Bytes_per_bin) {
case 1:
*p_byte++ = (char) ff;
break;
case 2:
*p_word++ = (short int) ff;
break;
case 4:
*p_long++ = (int) ff;
break;
}
}
}
}
/*
**---------------------------------------------------------------------------
** get_check_resources - get and check our resources
*/
int get_check_resources (
/* ===================
*/ XrmDatabase *db,
char *appName,
int *argc,
char *argv[],
int verbose) {
int i, status, len, do_help;
char buff[80];
char *type;
XrmValue value;
time_t time_now;
float tmp_secs;
/*---------------------------------------------------------- -help */
status = XrmGetResource (*db,
StrJoin (buff, sizeof (buff),
appName, ".sqhmHelp"),
"ProgramName.Values",
&type, &value);
do_help = (status) ? True : False;
if (do_help) {
show_help (NULL);
exit (EXIT_SUCCESS);
}
/*---------------------------------------------------------- -? */
status = XrmGetResource (*db,
StrJoin (buff, sizeof (buff),
appName, ".sqhmHelpItem"),
"ProgramName.Values",
&type, &value);
do_help = (status) ? True : False;
if (do_help) {
len = sizeof (buff);
StrEdit (buff, value.addr, "trim lowercase", &len);
show_help (buff);
exit (EXIT_SUCCESS);
}
/*---------------------------------------------------------- -verbose */
status = XrmGetResource (*db,
StrJoin (buff, sizeof (buff),
appName, ".sqhmVerbose"),
"ProgramName.Values",
&type, &value);
Verbose = verbose = (status) ? True : False;
/*---------------------------------------------------------- -host */
status = XrmGetResource (*db,
StrJoin (buff, sizeof (buff),
appName, ".sqhmHost"),
"ProgramName.Values",
&type, &value);
if (status) {
StrJoin (Rmt_host, sizeof (Rmt_host), value.addr, "");
}else {
if (*argc >= 2) {
StrJoin (Rmt_host, sizeof (Rmt_host), argv[1], "");
(*argc)--;
for (i = 1; i < *argc; i++) argv[i] = argv[i+1];
}else {
printf ("\n"
" Target host not specified, there is no default!\n");
show_help (NULL);
exit (EXIT_FAILURE);
}
}
if (verbose) printf ("Target host is \"%s\".\n", Rmt_host);
/*---------------------------------------------------------- -port */
status = XrmGetResource (*db,
StrJoin (buff, sizeof (buff),
appName, ".sqhmPort"),
"ProgramName.Values",
&type, &value);
if (!status || (sscanf (value.addr, "%d", &Rmt_port) != 1)) {
Rmt_port = 2400;
if (verbose) printf ("Using the default TCP/IP port number of ");
}else {
if (verbose) printf ("TCP/IP port number = ");
}
if (verbose) printf ("%d\n", Rmt_port);
/*---------------------------------------------------------- -pktsize */
status = XrmGetResource (*db,
StrJoin (buff, sizeof (buff),
appName, ".sqhmPktSize"),
"ProgramName.Values",
&type, &value);
if (!status || (sscanf (value.addr, "%d", &Pkt_size) != 1)) {
Pkt_size = 8192;
if (verbose) printf ("Using the default packet size of ");
}else {
if (verbose) printf ("Packet size = ");
}
if (verbose) printf ("%d\n", Pkt_size);
/*---------------------------------------------------------- -debug */
status = XrmGetResource (*db,
StrJoin (buff, sizeof (buff),
appName, ".sqhmDebug"),
"ProgramName.Values",
&type, &value);
Dbg_mode = (status) ? 1 : 0;
/*----------------------------------------------------------*/
return True;
}
/*
**----------------------------------------------------------------------------*/
int get_recd (FILE *lun, char *recd, int recd_len) {
/* ========
** Get a non-comment record from a file
*/
int nbytes = -1;
while (nbytes <= 0) {
if (fgets (recd, (recd_len - 1), lun) == NULL) return False;
nbytes = recd_len;
StrEdit (recd, recd, "trim compress uncomment", &nbytes);
}
return True;
}
/*
**--------------------------------------------------------------------------*/
void new_config_quit (
/* ===============
** Quit because SinqHM config'n has changed.
**
*/ char *txt) {
printf ("\n"
" It looks as though the configuration of SinqHM has been changed\n"
" whilst we were not looking. This should not be possible!\n"
" Please report the incident.\n"
" The item which has changed is \"%s\".\n\n", txt);
exit (EXIT_FAILURE);
}
/*
**--------------------------------------------------------------------------*/
int openConnection (
/* ==============
** Open connection to histogram memory front-end.
** Return value is socket id for communication with server.
** On successful connection, the SQHM_CNCT status reply
** is returned in <request>.
*/
char *node,
int *port, /* <== this arg gets modified! */
int *pkt_size, /* <== this arg gets modified! */
int mode,
struct rply_buff_struct *reply, /* <== this arg gets modified! */
int verbose) {
int i, status;
int my_skt = 0;
struct sockaddr_in lcl_sockname;
struct sockaddr_in rmt_sockname;
int rmt_inet_addr;
struct in_addr *rmt_inet_addr_pntr;
struct hostent *rmt_hostent;
int rmt_sockname_len;
/*
** Get Internet address of the front-end.
*/
for (i=0; i < strlen (node); i++) node[i] = tolower (node[i]);
rmt_hostent = gethostbyname (node);
if (rmt_hostent == NULL) {
/*
** The following code is to handle nodes which are not yet
** in the BIND data base.
*/
if (strcmp (node, "sqfe01") == 0) {
rmt_inet_addr_pntr = (struct in_addr *) &rmt_inet_addr;
rmt_inet_addr = inet_addr ("129.129.56.181");
}else {
printf ("Server Node is %s.\n", node);
FailInet ("\nopenConnection/Gethostbyname error.");
}
}else {
rmt_inet_addr_pntr = (struct in_addr *) rmt_hostent->h_addr_list[0];
}
printf (" SinqHM Server is %s ", rmt_hostent->h_name);
printf ("(%s),", inet_ntoa (*rmt_inet_addr_pntr));
printf (" Base port %d\n", *port);
/*
** Create a TCP/IP socket for prelim. connect to server and bind it.
*/
Cnct_skt = socket (AF_INET, SOCK_STREAM, 0);
if (Cnct_skt == -1) FailInet ("openConnection -- Cnct_skt socket error.\n");
lcl_sockname.sin_family = AF_INET;
lcl_sockname.sin_port = htons (0);
lcl_sockname.sin_addr.s_addr = 0;
status = bind (Cnct_skt, (struct sockaddr *) &lcl_sockname,
sizeof (lcl_sockname));
if (status == -1) FailInet ("openConnection -- Cnct_skt bind error.\n");
/*
**========================================= Now connect to the server.
*/
rmt_sockname_len = sizeof (rmt_sockname);
rmt_sockname.sin_family = AF_INET;
rmt_sockname.sin_port = htons (*port);
rmt_sockname.sin_addr.s_addr = rmt_inet_addr_pntr->s_addr;
status = connect (Cnct_skt, (struct sockaddr *) &rmt_sockname,
sizeof (rmt_sockname));
if (status == -1) {
GetErrno (&My_errno, &My_vaxc_errno);
FailInet ("openConnection -- connect error\n");
}
/*
**============================== Set up and send a connection request message.
*/
Req_buff.bigend = htonl (0x12345678);
Req_buff.cmnd = htonl (SQHM_CNCT);
Req_buff.u.cnct.max_pkt = htonl (*pkt_size);
Req_buff.u.cnct.strt_mode = htonl (mode);
if (mode != 0) {
printf (" Warning -- mode = %d\n", mode);
printf (" Use the debugger in the Hist Mem to get our server to run.\n");
}
status = send (Cnct_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
if (status == -1) FailInet ("openConnection -- Cnct-Socket send error\n");
if (status != sizeof (Req_buff)) {
printf ("SinqHM_Client -- wrong number of bytes sent: %d\n", status);
exit (EXIT_FAILURE);
}
/*
** Wait for the response telling us the port to use.
*/
status = recv (Cnct_skt, (char *) &Rply_buff, sizeof (Rply_buff), 0);
if (status == -1) {
FailInet ("openConnection -- Cnct-Socket recv error\n");
}else if (status != sizeof (Rply_buff)) {
printf ("SinqHM_Client -- Cnct-Socket recv error - ");
printf ("unexpected byte count: %d.\n", status);
exit (EXIT_FAILURE);
}
if (ntohl (reply->bigend) != 0x12345678) {
printf (
"SinqHM_Client -- big-endian/little-endian problem!\n"
" Buffer received in non-network byte order!\n");
exit (EXIT_FAILURE);
}
status = ntohl (reply->status);
if (status != KER__SUCCESS) {
if (status == KER__BAD_STATE) {
printf (" SinqHM_Client -- Histogram memory has not yet been "
"configured!\n");
print_uptime (stdout, " Up-time = ", ntohl (reply->u.cnct.up_time),
"\n");
}else if (status == KER__BAD_CREATE) {
status = ntohl (reply->sub_status);
printf (
"SinqHM_Client -- creation of histogram memory server process "
"failed!\n"
" Sub-status = ");
switch (status) {
case -1: printf ("%d. Spawn failed.\n", status); break;
case -2: printf ("%d. No more ports available.\n", status); break;
case -3: printf ("%d. Time-out.\n", status); break;
case -4: printf ("%d. Child process detected a problem "
"during startup.\n", status); break;
default: printf ("%d. Undefined. Refer to the source code!\n", status);
}
}else {
printf ("SinqHM_Client -- Bad and unrecognised status from Connect "
"Request: %d.\n", status);
}
exit (EXIT_FAILURE);
}
status = close (Cnct_skt);
Cnct_skt = 0;
if (status != 0) FailInet ("openConnection -- Cnct-Socket close error\n");
*port = ntohl (reply->u.cnct.port);
if (verbose) printf (" Server port to use = %6d\n", *port);
*pkt_size = ntohl (reply->u.cnct.pkt_size);
if (verbose) printf (" Agreed packet size = %6d\n", *pkt_size);
/*
** Now create, bind and connect a TCP/IP socket to our remote server port.
*/
my_skt = socket (AF_INET, SOCK_STREAM, 0);
if (my_skt == -1) {
FailInet ("openConnection -- Srvr-Skt socket error.\n");
return 0;
}
lcl_sockname.sin_family = AF_INET;
lcl_sockname.sin_port = htons (0);
lcl_sockname.sin_addr.s_addr = 0;
status = bind (my_skt, (struct sockaddr *) &lcl_sockname,
sizeof (lcl_sockname));
if (status == -1) {
FailInet ("openConnection -- Srvr-Skt bind error.\n");
return 0;
}
rmt_sockname_len = sizeof (rmt_sockname);
rmt_sockname.sin_family = AF_INET;
rmt_sockname.sin_port = htons (*port);
rmt_sockname.sin_addr.s_addr = rmt_inet_addr_pntr->s_addr;
status = connect (my_skt, (struct sockaddr *) &rmt_sockname,
sizeof (rmt_sockname));
if (status == -1) {
GetErrno (&My_errno, &My_vaxc_errno);
FailInet ("openConnection -- Srvr-Skt connect error\n");
return 0;
}
Rw_bytes_got = 0; Rw_bytes_put = 0;
return my_skt;
}
/*
**--------------------------------------------------------------------------*/
int openConnectionGbl (
/* =================
** Call openConnection then set up some global variables.
* Return value is socket id for communication with server.
*/
char *node,
int *port, /* <== this arg gets modified! */
int *pkt_size, /* <== this arg gets modified! */
int mode,
struct rply_buff_struct *reply, /* <== this arg gets modified! */
int verbose) {
int my_skt = 0;
my_skt = openConnection (node, port, pkt_size, mode, reply, verbose);
if (my_skt == 0) return my_skt;
Hm_mode = ntohl (Rply_buff.u.cnct.hm_mode);
if (verbose) print_HM_mode (Hm_mode, 10);
N_hists = ntohl (Rply_buff.u.cnct.n_hists);
if (verbose && (N_hists != 1))
printf (" Number of histograms = %6d\n", N_hists);
Hm_nbins = ntohl (Rply_buff.u.cnct.num_bins);
if (verbose) printf (" Number of bins per histogram = %6d\n", Hm_nbins);
Compress = ntohl (Rply_buff.u.cnct.compress);
if ((verbose) && (Compress > 1))
printf (" Bin span = %6d\n", Compress);
if (verbose && (N_hists > 1))
printf (" Total number of bins = %6d\n", N_hists * Hm_nbins);
Bytes_per_bin = ntohl (Rply_buff.u.cnct.bytes_per_bin);
if (verbose)
printf (" Number of bytes per bin = %6d\n", Bytes_per_bin);
Lo_cntr = ntohl (Rply_buff.u.cnct.lo_cntr);
if (verbose && (Lo_cntr != 0))
printf (" Low counter number = %6d\n", Lo_cntr);
Lo_bin = ntohl (Rply_buff.u.cnct.lo_bin);
if (verbose && (Lo_bin != 0))
printf (" Low counter number = %6d\n", Lo_bin);
Curr_hist = ntohl (Rply_buff.u.cnct.curr_hist);
if (verbose && (Curr_hist != 0))
printf (" Current histogram = %6d\n", Curr_hist);
Total_bytes = ntohl (Rply_buff.u.cnct.total_bytes);
if (verbose)
printf (" Histogram buffer size = %6d bytes\n", Total_bytes);
Max_block = ntohl (Rply_buff.u.cnct.max_block);
if (verbose)
printf (" Free memory space available = %6d bytes\n", Max_block);
return my_skt;
}
/*
**--------------------------------------------------------------------------
*/
void print_HM_mode (
/* =============
** Interpret the HM configuration.
**
*/ uint mode, /* The configuration to be interpreted */
int n_pad) { /* A padding count to move the "=" */
uint my_mode;
printf (" Histogramming Mode%*s = 0x%x", n_pad, "", mode);
my_mode = mode & (~SQHM__SUB_MODE_MSK);
if (my_mode == SQHM__TRANS) printf (" TRANS");
if (my_mode == SQHM__HM_DIG) printf (" HM_DIG");
if (my_mode == SQHM__TOF) printf (" TOF");
if (my_mode == SQHM__HM_PSD) printf (" HM_PSD");
if (my_mode == SQHM__HRPT) printf (" HRPT");
if ((mode & SQHM__DEBUG) != 0) printf (" DEBUG");
if ((mode & SQHM__UD) != 0) printf (" UD");
if ((mode & SQHM__STROBO) != 0) printf (" STROBO");
if ((mode & SQHM__REFLECT) != 0) printf (" REFLECT");
if ((mode & SQHM__NO_STAT) != 0) printf (" NO_FILLER_STATUS");
printf ("\n");
printf (" Bin Overflow Mode %*s = ", n_pad, "");
my_mode = mode & SQHM__BO_MSK;
if (my_mode == SQHM__BO_IGN) {
printf ("\"Ignore\"\n");
}else if (my_mode == SQHM__BO_SMAX) {
printf ("\"Stop-at-Max\"\n");
}else if (my_mode == SQHM__BO_CNT) {
printf ("\"Count\"");
}else {
printf ("\"Unrecognised\" = 0x%x\n", my_mode);
}
}
/*
**--------------------------------------------------------------------------*/
void print_uptime (
/* ============
** Print out the up-time
*/
FILE *lun, /* The output stream */
char *prefix, /* A message prefix */
int secs, /* The up-time in seconds */
char *suffix) { /* A message suffix */
int mins, hrs, days;
mins = secs/60; secs -= mins * 60;
hrs = mins/60; mins -= hrs * 60;
days = hrs/24; hrs -= days * 24;
fprintf (lun, "%s", prefix);
if (days > 0) {
printf (" %d days, %d%02d%02d%s", days, hrs, mins, secs, suffix);
}else if (hrs > 0) {
printf (" %d hrs, %d mins, %d secs%s", hrs, mins, secs, suffix);
}else if (mins > 0) {
printf (" %d mins, %d secs%s", mins, secs, suffix);
}else {
printf (" %d secs%s", secs, suffix);
}
}
/*
**--------------------------------------------------------------------------*/
int read_hm (
/* =======
** Read block of bins from SINQHM_SRV
*/
char *hbuf, /* Buffer to hold data */
uint hbuf_size, /* Size of hbuf */
uint f_bin, /* First bin to read */
uint n_bins, /* Number of bins to read */
uint hist_no, /* Histogram number to read */
uint *cntr_lo, /* # events below histo range */
uint *cntr_hi) { /* # events above histo range */
/*
** Send SQHM_READ request to server to read n_bins hist mem bins
** starting at bin f_bin. On return, the data is in the buffer
** pointed to by Hm_buff_addr.
*/
int status, is, i;
int bytes_to_come;
uint my_n_bins, my_bytes_per_bin;
uchar *nxt_byte;
usint *nxt_word;
uint *nxt_long;
bytes_to_come = n_bins * Bytes_per_bin;
if (bytes_to_come > hbuf_size) {
printf ("read_hm: buffer is too small!\n"
" It is %d rather than %d bytes long.\n",
hbuf_size, bytes_to_come);
return EXIT_FAILURE;
}
status = EXIT_SUCCESS; /* Assume success. */
Req_buff.bigend = htonl (0x12345678);
Req_buff.cmnd = htonl (SQHM_READ);
Req_buff.u.read.n_bins = htonl (n_bins);
Req_buff.u.read.first_bin = htonl (f_bin);
Req_buff.u.read.hist_no = htonl (hist_no);
status = send (Rw_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
Rw_bytes_put += status;
if (status == -1) FailInet ("read_hm -- R/W-Socket send error\n");
if (status != sizeof (Req_buff)) {
printf ("read_hm: wrong number of bytes sent: %d", status);
return EXIT_FAILURE;
}
/*
** Wait for the status response.
*/
status = recv (Rw_skt, (char *) &Rply_buff, sizeof (Rply_buff), 0);
Rw_bytes_got += status;
if (status == -1) {
FailInet ("read_hm -- R/W-Socket recv error\n");
}else if (status != sizeof (Rply_buff)) {
printf ("read_hm: R/W-Socket recv error - ");
printf ("unexpected byte count: %d.\n", status);
return EXIT_FAILURE;
}
if (ntohl (Rply_buff.bigend) != 0x12345678) {
printf (
"read_hm: big-endian/little-endian problem!\n"
" Buffer received in non-network byte order!\n");
return EXIT_FAILURE;
}
if (ntohl (Rply_buff.status) != KER__SUCCESS) {
printf ("read_hm: Bad status from SQHM_READ Request: %d.\n",
ntohl (Rply_buff.status));
printf (" Sub-status: %d.\n",
ntohl (Rply_buff.sub_status));
if (Rply_buff.u.message[0] != NIL)
printf (" Message is: %s\n", Rply_buff.u.message);
return EXIT_FAILURE;
}
/*
** Data was read OK so read the data which has been sent.
*/
my_n_bins = ntohl (Rply_buff.u.read.n_bins);
my_bytes_per_bin = ntohl (Rply_buff.u.read.bytes_per_bin);
*cntr_lo = ntohl (Rply_buff.u.read.cnts_lo);
*cntr_hi = ntohl (Rply_buff.u.read.cnts_hi);
if (my_n_bins != n_bins) {
printf ("read_hm: "
"Warning -- server is sending us %d bins of data rather than %d!\n",
my_n_bins, n_bins);
}
bytes_to_come = my_n_bins * my_bytes_per_bin;
if (bytes_to_come > hbuf_size) {
printf ("read_hm: Warning -- buffer size = %d bytes\n"
" Server is sending us %d bytes of data.\n"
" Some data will have to be flushed!\n",
hbuf_size, bytes_to_come);
}
nxt_byte = (uchar *) Hm_buff_addr;
while (bytes_to_come > 0) {
i = (bytes_to_come > Pkt_size) ? Pkt_size : bytes_to_come;
if (bytes_to_come > hbuf_size) {
i = hbuf_size;
nxt_byte = (uchar *) Hm_buff_addr;
}
status = recv (Rw_skt, nxt_byte, i, 0);
Rw_bytes_got += status;
if (status == -1) FailInet ("read_hm -- R/W-Socket data recv error\n");
bytes_to_come = bytes_to_come - status;
nxt_byte = nxt_byte + status;
}
/*
** If byte swapping is necessary, do it!
*/
if ((Bytes_per_bin > 0) && (Rply_buff.bigend != 0x12345678)) {
switch (Bytes_per_bin) { /* Byte swapping is necessary */
case 2:
/* Not sure how to do this - this might be wrong! */
nxt_word = (usint *) Hm_buff_addr;
for (i = 0; i < n_bins; i++) nxt_word[i] = ntohs (nxt_word[i]);
break;
case 4:
nxt_long = (uint *) Hm_buff_addr;
for (i = 0; i < n_bins; i++) nxt_long[i] = ntohl (nxt_long[i]);
break;
}
}
return EXIT_SUCCESS;
}
/*
**--------------------------------------------------------------------------*/
int read_project (
/* ============
** Read projected block of bins from SINQHM_SRV.
** Send SQHM_PROJECT request to server.
** On return, the data is in the buffer pointed to by hbuf.
*/
char *hbuf, /* Buffer to hold data */
uint hbuf_size, /* Size of hbuf */
uint f_bin, /* First bin to read */
uint n_bins, /* Number of bins to read */
uint f_hist, /* First histogram to read */
uint n_hists, /* Number of histograms to read */
uint axis, /* Projection axis */
uint xdim, /* Pseudo-x-dimension */
uint h_select, /* Histogram to select (pseudo 2-d mode) */
uint *cntr_lo, /* # events below histo range */
uint *cntr_hi) { /* # events above histo range */
int status, is, i;
int bytes_to_come;
uint nbins_to_read, my_n_bins, my_bytes_per_bin;
uchar *nxt_byte;
usint *nxt_word;
uint *nxt_long;
nbins_to_read = (axis == 0) ? n_bins : n_hists;
bytes_to_come = nbins_to_read * sizeof (uint);
if (bytes_to_come > hbuf_size) {
printf ("read_project: buffer is too small!\n"
" It is %d rather than %d bytes long.\n",
hbuf_size, bytes_to_come);
return EXIT_FAILURE;
}
status = EXIT_SUCCESS; /* Assume success. */
Req_buff.bigend = htonl (0x12345678);
Req_buff.cmnd = htonl (SQHM_PROJECT);
i = (axis == 0) ? 0 : PROJECT__ON_Y;
if (xdim != 0) i |= PROJECT__1_DIM;
Req_buff.u.project.sub_code = htonl (i);
Req_buff.u.project.x_lo = htonl (f_bin);
Req_buff.u.project.nx = htonl (n_bins);
Req_buff.u.project.y_lo = htonl (f_hist);
Req_buff.u.project.ny = htonl (n_hists);
Req_buff.u.project.xdim = htonl (xdim);
Req_buff.u.project.nhist = htonl (h_select);
status = send (Rw_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
Rw_bytes_put += status;
if (status == -1) FailInet ("read_project -- R/W-Socket send error\n");
if (status != sizeof (Req_buff)) {
printf ("read_project: wrong number of bytes sent: %d", status);
return EXIT_FAILURE;
}
/*
** Wait for the status response.
*/
status = recv (Rw_skt, (char *) &Rply_buff, sizeof (Rply_buff), 0);
Rw_bytes_got += status;
if (status == -1) {
FailInet ("read_project -- R/W-Socket recv error\n");
}else if (status != sizeof (Rply_buff)) {
printf ("read_project: R/W-Socket recv error - ");
printf ("unexpected byte count: %d.\n", status);
return EXIT_FAILURE;
}
if (ntohl (Rply_buff.bigend) != 0x12345678) {
printf (
"read_project: big-endian/little-endian problem!\n"
" Buffer received in non-network byte order!\n");
return EXIT_FAILURE;
}
if (ntohl (Rply_buff.status) != KER__SUCCESS) {
printf ("read_project: Bad status from SQHM_READ Request: %d.\n",
ntohl (Rply_buff.status));
printf (" Sub-status: %d.\n",
ntohl (Rply_buff.sub_status));
if (Rply_buff.u.message[0] != NIL)
printf (" Message is: %s\n", Rply_buff.u.message);
return EXIT_FAILURE;
}
/*
** Data was read OK so read the data which has been sent.
*/
my_n_bins = ntohl (Rply_buff.u.project.n_bins);
my_bytes_per_bin = ntohl (Rply_buff.u.project.bytes_per_bin);
*cntr_lo = ntohl (Rply_buff.u.project.cnts_lo);
*cntr_hi = ntohl (Rply_buff.u.project.cnts_hi);
if (my_n_bins != nbins_to_read) {
printf ("read_project: Warning -- "
"server is sending us %d bins of data rather than %d!\n",
my_n_bins, n_bins);
}
bytes_to_come = my_n_bins * my_bytes_per_bin; /* Compute length of data */
if (bytes_to_come > hbuf_size) {
printf ("read_project: Warning -- buffer size = %d bytes\n"
" Server is sending us %d bytes of data.\n"
" Some data will have to be flushed!\n",
hbuf_size, bytes_to_come);
}
nxt_byte = (uchar *) hbuf;
while (bytes_to_come > 0) {
i = (bytes_to_come > Pkt_size) ? Pkt_size : bytes_to_come;
if (bytes_to_come > hbuf_size) {
i = hbuf_size;
nxt_byte = (uchar *) hbuf;
}
status = recv (Rw_skt, nxt_byte, i, 0);
Rw_bytes_got += status;
if (status == -1) FailInet ("read_project -- R/W-Socket data recv error\n");
bytes_to_come = bytes_to_come - status;
nxt_byte = nxt_byte + status;
}
/*
** If byte swapping is necessary, do it!
*/
if ((my_bytes_per_bin > 0) && (Rply_buff.bigend != 0x12345678)) {
switch (my_bytes_per_bin) { /* Byte swapping is necessary */
case 2:
/* Not sure how to do this - this might be wrong! */
nxt_word = (usint *) hbuf;
for (i = 0; i < nbins_to_read; i++) nxt_word[i] = ntohs (nxt_word[i]);
break;
case 4:
nxt_long = (uint *) hbuf;
for (i = 0; i < nbins_to_read; i++) nxt_long[i] = ntohl (nxt_long[i]);
break;
}
}
return EXIT_SUCCESS;
}
/*
**---------------------------------------------------------------------------
** setup_xrm_database - setup Resource Manager Database
*/
int setup_xrm_database (
/* ==================
*/ XrmDatabase *db,
char *name[],
int *argc,
char *argv[],
int verbose) {
static char our_name[80] = "Unknown"; /* This holds the program name */
static char lkup_name[80] = "Unknown"; /* Name for looking in database */
int status, i, first = True;
char text[80];
char full_nm0[80];
char full_nm1[80];
char *p_fil[] = {0,0,0,0,0,0,0,0,0,0};
char *my_name;
char *my_name_last;
char *name_type;
XrmValue name_value;
XrmDatabase cmnd_line_db = NULL;
XrmDatabase lcl_db = NULL;
/*-----------------------------------------------------
** This routine merges some resource databases with options specified on
** the command line. Resources can then be looked up using XrmGetResource.
** This is a bit like the X-toolkit routine XtAppInitialize does for the
** extraction of resources by XtGetApplicationResources.
**
** I can't help but think that there's a simpler way of doing this but I
** can't find it in the X manuals. Basically, the problem arises with wanting
** to avoid the calling program being associated with an X-display, i.e. it
** is intended for use by "command-line oriented" programs. All the nice,
** easy-to-use resource/command-line setup routines in Xlib or Xtlib seem to
** assume one is going to use a display -- not surprising, I suppose,
** since the concept of Xlib is for writing window based applications!
**
** Anyway, the point is that the following way turns out to be lacking
** when it gets tested in anger.
*/
status = True; /* Assume success */
our_name[0] = NIL;
/*
** Make a list of the databases to be merged, highest priority first.
*/
#ifdef __VMS
p_fil[0] = "decw$user_defaults:SinQ_rc.dat";
p_fil[1] = "decw$group_defaults:SinQ_rc.dat";
p_fil[2] = "decw$system_defaults:SinQ_rc.dat";
p_fil[3] = "decw$user_defaults:decw$xdefaults.dat";
p_fil[4] = "decw$group_defaults:decw$xdefaults.dat";
p_fil[5] = "decw$system_defaults:decw$xdefaults.dat";
p_fil[6] = NULL;
if (*argc > 0) { /* Find out what we are called - parse file nm */
my_name = strstr (argv[0], "]"); /* Find end of directory, i.e. "]" */
my_name++; /* Skip over "]" */
if (my_name[0] == '[') { /* Handle possible concealed device */
my_name = strstr (my_name, "]");
my_name++;
}
i = sizeof (our_name);
StrEdit (our_name, my_name, "lowercase", &i); /* Copy the rest */
strtok (our_name, "."); /* Close it off at "." */
}
#else
p_fil[0] = StrJoin (full_nm0, sizeof (full_nm0),
getenv ("HOME"), "/SinQ_rc");
p_fil[1] = "/usr/lib/X11/app-defaults/SinQ_rc";
p_fil[2] = StrJoin (full_nm1, sizeof (full_nm1),
getenv ("HOME"), "/.Xdefaults");
p_fil[3] = "/usr/lib/X11/app-defaults/Xdefaults";
p_fil[4] = NULL;
if (*argc > 0) { /* Find out what we are called - parse file nm */
/* Find end of directories */
my_name = argv[0] - 1;
while (my_name != NULL) {
my_name_last = my_name;
my_name_last++;
my_name = strstr (my_name_last, "/");
}
StrJoin (our_name, sizeof (our_name), my_name_last, "");
}
#endif
if (verbose) printf ("My name is \"%s\"\n", our_name);
/*
** Initialise and combine all databases
*/
XrmInitialize ();
for (i = 0; i < XtNumber (p_fil); i++) {
if (p_fil[i] == NULL) break;
status = XrmCombineFileDatabase (p_fil[i], &lcl_db, False);
if ((status != 0) && verbose) {
if (first)
printf ("Resource database created from file %s.\n", p_fil[i]);
if (!first)
printf ("File %s merged into resource database.\n", p_fil[i]);
first = False;
}
}
/*----------------------------------------------------------------
** See if there's anything specified on cmnd line, incl "name".
*/
XrmParseCommand (&cmnd_line_db,
OpTable_0, XtNumber(OpTable_0), our_name, argc, argv);
if (cmnd_line_db != NULL) {
/*
** There was at least 1 item on cmnd line. Process the line.
** If -name was specified, adopt it.
*/
status = XrmGetResource (cmnd_line_db, /* See if a name was specified */
StrJoin (text, sizeof (text), our_name, ".name"),
"ProgramName.Values",
&name_type, &name_value);
if (status) {
i = sizeof (lkup_name);
StrEdit (lkup_name, name_value.addr, "lowercase", &i);
printf ("Option list name is \"%s\"\n", lkup_name);
}else {
strcpy (lkup_name, our_name);
}
/*
** Loop over all items in OpTable_0 and merge them into database,
** taking care of any possible name changes.
*/
for (i = 0; i < XtNumber (OpTable_0); i++) {
if (strcmp (OpTable_0[i].option, "-name") == 0) continue;
status = XrmGetResource (cmnd_line_db,
StrJoin (text, sizeof (text),
our_name, OpTable_0[i].specifier),
"ProgramName.Values",
&name_type, &name_value);
if (status) {
StrJoin (text, sizeof (text), lkup_name, OpTable_0[i].specifier);
XrmPutResource (&lcl_db, text, "String", &name_value);
}
}
}
/*----------------------------------------------------------------
*/
*name = lkup_name;
*db = lcl_db;
if ((lcl_db == NULL) && verbose)
printf ("Warning -- no resource database found.\n");
XrmDestroyDatabase (cmnd_line_db);
/*
** XrmPutFileDatabase (lcl_db, "sinqhm_client.db");
*/
return status;
}
/*
**--------------------------------------------------------------------------*/
void show_help (char *token) {
/* =========
** Display help text
*/
int len;
if (token == NULL) token = "";
if (token[0] == NIL) {
printf ("\n"
" The following commands are recognised by SinqHM_Client:\n"
"\n"
" Help or ? - generate this help information\n"
" Open or - open the connection to the histogram memory\n"
" Connect\n"
" Status or - show the status of the histogram memory\n"
" Show\n"
" Read - read a region of histogram memory\n"
" 2D - read a region of a 2-dimensional histogram\n"
" Project - read a projected region of a 2-dim histogram\n"
" Dump - dump the contents of the histogram buffer\n"
" LOAD - write the histogram buffer from a file\n"
" WRIte - write data to a histogram region\n"
" W2D - write data to a histogram region in pseudo 2-dim mode\n"
" GO - start data acquisition\n"
" STOP - stop data acquisition\n"
" ZERO - zero a region of histogram memory\n"
" Quit or - end the program\n"
" Exit or End\n"
"\n"
" To get more detailed help on a specific command, issue "
"the command:\n"
"\n"
" ? <cmnd>\n"
"\n"
" For information on environment setup for SinqHM_Client, issue"
"the command:\n"
"\n"
" ? SETUP\n"
"\n");
} else {
len = strlen (token);
if (StrMatch (token, "read", 1)) {
printf ("\n"
" Read <1st-bin> <#-bins> <hist-#>\n"
" ^ ^ ^\n"
" | | |\n"
" | | +--- Dflt = -1\n"
" | +------------ Dflt = see below\n"
" +--------------------- Dflt = 0\n"
"\n"
" Read <#-bins> bins starting at <1st-bin> of histogram <hist-#>.\n"
"\n"
" If <hist-#> is -1, the histogram data is regarded as a single "
"histogram.\n"
" The default for <#-bins> depends on the value of <hist-#>. "
"If <hist-#>\n"
" is -1, it defaults to the total histogram size (i.e. "
"<#-bins-per-hist> *\n"
" <#-histograms>). Otherwise, it defaults to <#-bins-per-hist>.\n"
"\n"
" The command verb should be terminated by a space or tab.\n"
" Arguments may be separated by spaces, tabs or commas.\n"
"\n"
" Hence, to read the whole of histogram number 5, for example, "
"specify:\n"
"\n"
" READ ,,5\n"
"\n");
}else if (StrMatch (token, "2d", 2)) {
printf ("\n"
" 2D <1st-hist> <#-hists> <1st-bin> <#-bins>\n"
" ^ ^ ^ ^\n"
" | | | |\n"
" | | | +--- Dflt = histogram size\n"
" | | +------------ Dflt = 0\n"
" | +---------------------- Dflt = number of histograms\n"
" +--------------------------------- Dflt = 0\n"
"\n"
" Read a rectangular array of the 2-dim histogram memory (e.g. a TOF\n"
" spectrum). From each histogram, <#-bins> bins starting at <1st-bin>\n"
" are read. The same region is read from histograms <1st-hist> to\n"
" <1st-hist>+<#-hists>-1.\n"
"\n");
}else if (StrMatch (token, "project", 1)) {
printf ("\n"
" Project <1st-hist>, <-- dflt = 0.\n"
" <#-hists>, <-- dflt = number of histograms.\n"
" <1st-bin>, <-- dflt = 0.\n"
" <#-bins>, <-- dflt = histogram size.\n"
" <axis>, <-- \"X\" or \"Y\" for proj'n onto x- or "
"y-axis. Dflt = \"X\".\n"
" <x-dim>, <-- gives x-extent of histog in pseudo-2-"
"dim mode.\n"
" <hist-#> <-- selects a histogram in pseudo-2-dim "
"mode. Dflt = 0.\n"
"\n"
" Read a rectangular array of the 2-dim histogram memory (e.g. "
"a TOF\n"
" spectrum) projected onto the x or y axis. From each histogram, "
"<#-bins> bins\n"
" starting at <1st-bin> are read. The same region is read"
"from histograms\n"
" <1st-hist> to <1st-hist>+<#-hists>-1.\n"
"\n"
" If <x-dim> is non-zero, pseudo-2-dim mode will be assumed "
"(i.e. the\n"
" PROJECT__1_DIM sub_code bit will be set.\n"
"\n");
}else if (StrMatch (token, "dump", 1)) {
printf ("\n"
" DUMP <1st-bin> <#-bins> <file>\n"
" ^ ^ ^\n"
" | | |\n"
" | | +---- Dflt = standard output\n"
" | +------------ Dflt = rest of buffer\n"
" +--------------------- Dflt = 0\n"
"\n"
" Dump <#-bins> bins starting at <1st-bin> of buffer.\n"
"\n"
" The command verb should be terminated by a space or tab.\n"
" Arguments may be separated by spaces, tabs or commas.\n"
"\n"
" Hence, to dump 25 bins starting at bin 100, specify:\n"
"\n"
" DUMP 100,25\n"
"\n");
}else if (StrMatch (token, "load", 1)) {
printf ("\n"
" LOAD <file>\n"
" ^\n"
" |\n"
" +---- Dflt = standard input\n"
"\n"
" Read the contents of the file and write to hist mem.\n"
" The file format should be the same as that generated by DUMP\n"
"\n");
}else if (StrMatch (token, "write", 2)) {
printf ("\n"
" WRITE <p1> <p2> <p3> <p4> <p5> <p6>\n"
" ^ ^ ^ ^ ^ ^\n"
" | | | | | |\n"
" | | | | | +--- Dflt = 0.60 * Number of bins\n"
" | | | | +-------- Dflt = 1000\n"
" | | | +------------- Dflt = 200000\n"
" | | +------------------ Dflt = 0.23 * Number of bins\n"
" | +----------------------- Dflt = 1000\n"
" +---------------------------- Dflt = 2000000\n"
"\n"
" Preset the histogram memory to the sum of 2 Lorenzians given by\n"
" <p1> ... <p6>.\n"
"\n");
}else if (StrMatch (token, "w2d", 2)) {
printf ("\n"
" WRITE <#-hists> <p1> <p2> <p3> <p4> <p5> <p6>\n"
" ^ ^ ^ ^ ^ ^ ^\n"
" | | | | | | |\n"
" | | | | | | +--- Dflt = 0.60 * Number of bins\n"
" | | | | | +-------- Dflt = 1000\n"
" | | | | +------------- Dflt = 200000\n"
" | | | +------------------ Dflt = 0.23 * Number of bins\n"
" | | +----------------------- Dflt = 1000\n"
" | +---------------------------- Dflt = 2000000\n"
" +--------- Dflt = 1. The total allocated hist mem is\n"
" split into <#-hists> histograms.\n"
"\n"
" Preset the histogram memory to the sum of 2 Lorenzians given by\n"
" <p1> ... <p6>.\n"
"\n");
}else if (StrMatch (token, "go", 1)) {
printf ("\n"
" GO\n"
"\n"
" Start data acquisition.\n"
"\n");
}else if (StrMatch (token, "show", 2)) {
printf ("\n"
" SHOW\n"
"\n"
" Show Hist Mem status.\n"
"\n");
}else if (StrMatch (token, "stop", 2)) {
printf ("\n"
" STOP\n"
"\n"
" Stop data acquisition.\n"
"\n");
}else if (StrMatch (token, "zero", 1)) {
printf ("\n"
" ZERO <1st-bin> <#-bins>\n"
" ^ ^\n"
" | |\n"
" | +---- Dflt = histogram size\n"
" +------------- Dflt = 0\n"
"\n"
" Zero <#-bins> bins starting at <1st-bin>.\n"
"\n");
}else if ((StrMatch (token, "open", 1)) ||
(StrMatch (token, "connect", 1))) {
if (StrMatch (token, "open", 1)) {
printf ("\n OPEN\n\n");
}else {
printf ("\n CONNECT\n\n");
}
printf (
" Open the connection to the Hist Mem.\n"
" The connection is usually not opened until the first "
"action command\n"
" is given.\n"
"\n");
}else if (StrMatch (token, "setup", 2)) {
printf ("\n"
" The following environment variables should be set on Unix systems:\n"
"\n"
" setenv SINQHM_FRONTEND \"<host> <port> <pkt-size>\"\n"
" setenv SINQHM_DBG_MODE <mode>\n"
"\n"
" The following logical names should be set on VMS systems:\n"
"\n"
" DEFINE/GROUP SINQHM_FRONTEND \"<host> <port> <pkt-size>\"\n"
" DEFINE/GROUP SINQHM_DBG_MODE <mode>\n"
"\n"
" Defaults:\n"
" <host> None <mode> 0\n"
" <port> 2400\n"
" <pkt-size> 8192\n"
"\n"
" If <mode> is non-zero, the server will suspend itself to allow debugging.\n"
"\n");
}else {
printf ("Sorry, no help available for \"%s\"!\n", token);
}
}
}
/*
**--------------------------------------------------------------------------*/
void split_args (
/* ==========
** Split up a text string into arguments. The arguments
** may be separated by white space or commas. Adjacent
** commas indicate a default argument.
**
** Each argument in the variable length argument list will
** get set to the address of the start of the appropriate
** argument. A defaulted argument is returned as NULL.
*/
char *str, /* The string to be parsed. This string will get modified
** as it is split up into tokens */
...) { /* A NULL terminated list of char** arguments. */
va_list ap; /* Pointer to variable args */
int i, s_len, l_nxt;
char *nxt_str;
char **arg_ptr;
va_start (ap, str); /* Set up var arg machinery */
s_len = strlen (str);
if (s_len <= 0) { /* If input string is null, return lots of NULLs */
arg_ptr = va_arg (ap, char **);
while (arg_ptr != NULL) {
*arg_ptr = NULL;
arg_ptr = va_arg (ap, char **);
}
return;
}
/* Turn all white space chars into spaces */
l_nxt = strcspn (str, "\t\f\v\n");
while (l_nxt != s_len) {
str[l_nxt] = ' ';
l_nxt = strcspn (str, "\t\f\v\n");
}
/* Now compress out multiple spaces */
nxt_str = strstr (str, " ");
while (nxt_str != NULL) {
nxt_str[1] = NIL;
StrJoin (str, (s_len + 1), str, &nxt_str[2]);
nxt_str = strstr (str, " ");
}
if (str[0] == ' ') str++; /* Remove a leading space, if present */
/* Remove a space if followed by a comma */
nxt_str = strstr (str, " ,");
while (nxt_str != NULL) {
nxt_str[0] = NIL;
StrJoin (str, (s_len + 1), str, &nxt_str[1]);
nxt_str = strstr (str, " ,");
}
/* Remove a space if preceded by a comma */
nxt_str = strstr (str, ", ");
while (nxt_str != NULL) {
nxt_str[1] = NIL;
StrJoin (str, (s_len + 1), str, &nxt_str[2]);
nxt_str = strstr (str, ", ");
}
/* Turn all remaining spaces into commas */
s_len = strlen (str);
l_nxt = strcspn (str, " ");
while (l_nxt != s_len) {
str[l_nxt] = ',';
l_nxt = strcspn (str, " ");
}
/* Now split up the comma-separated tokens */
arg_ptr = va_arg (ap, char **); /* Get pntr to first argument */
while (arg_ptr != NULL) { /* Loop till all have been done */
if (strlen (str) == 0) {
*arg_ptr = NULL; /* If str is exhausted, keep giving NULL */
}else {
l_nxt = strcspn (str, ","); /* Find end of next token */
if (l_nxt > 0) { /* Is it a null token? */
*arg_ptr = str; /* No, so set up next arg pntr */
str[l_nxt] = NIL; /* Terminate the token */
str = &str[l_nxt+1]; /* Move over the separator */
}else { /* It is a null token */
*arg_ptr = NULL;
str++; /* Move over the separator */
}
}
arg_ptr = va_arg (ap, char **); /* Get pntr to next parameter ident */
}
}
/*
**--------------------------------------------------------------------------*/
int write_hm (
/* ========
** Write block of bins to SINQHM_SRV
*/
void *hbuf, /* Buffer holding data */
uint hist_no, /* Histogram number to write */
uint f_bin, /* First bin to write */
uint n_bins, /* Number of bins to write */
uint bpb) { /* # bytes per bin */
int i, status, bytes_to_go;
uchar *p_byte;
usint *p_word;
uint *p_long;
p_byte = (uchar *) hbuf;
p_word = (usint *) hbuf;
p_long = (uint *) hbuf;
if (0x12345678 != ntohl (0x12345678)) { /* Swap bytes, if necessary */
switch (bpb) {
case 1: break;
case 2: for (i=0; i<n_bins; i++) p_word[i] = htons (p_word[i]); break;
case 4: for (i=0; i<n_bins; i++) p_long[i] = htonl (p_long[i]);
}
}
/*
** Send the request message first
*/
Req_buff.bigend = htonl (0x12345678);
Req_buff.cmnd = htonl (SQHM_WRITE);
Req_buff.u.write.hist_no = htonl (hist_no);
Req_buff.u.write.n_bins = htonl (n_bins);
Req_buff.u.write.first_bin = htonl (f_bin);
Req_buff.u.write.bytes_per_bin = htonl (bpb);
status = send (Rw_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
if (status == -1) FailInet ("write_hm -- R/W-Socket send error\n");
if (status != sizeof (Req_buff)) {
printf ("SinqHM_Client -- wrong number of bytes sent: %d", status);
exit (EXIT_FAILURE);
}
/*
** Now send the data.
*/
bytes_to_go = n_bins * bpb;
p_byte = (uchar *) hbuf;
while (bytes_to_go > 0) {
i = (bytes_to_go > Pkt_size) ? Pkt_size : bytes_to_go;
status = send (Rw_skt, (char *) p_byte, i, 0);
if (status <= 0) {
FailInet ("write_hm -- R/W-Socket send error\n");
exit (EXIT_FAILURE);
}
bytes_to_go -= status;
p_byte += status;
}
/*
** Now get the server's status message.
*/
status = recv (Rw_skt, (char *) &Rply_buff, sizeof (Rply_buff), 0);
if (status == -1) {
FailInet ("write_hm -- R/W-Socket recv error\n");
exit (EXIT_FAILURE);
}else if (status != sizeof (Rply_buff)) {
printf ("SinqHM_Client -- Cnct-Socket recv error - ");
printf ("unexpected byte count: %d.\n", status);
exit (EXIT_FAILURE);
}
if (ntohl (Rply_buff.bigend) != 0x12345678) {
printf (
"SinqHM_Client -- big-endian/little-endian problem!\n"
" Buffer received in non-network byte order!\n");
exit (EXIT_FAILURE);
}else if (ntohl (Rply_buff.status) != KER__SUCCESS) {
printf ("SinqHM_Client -- Bad status from Write Request: %d.\n",
ntohl (Rply_buff.status));
printf (" \"%s\"\n", Rply_buff.u.message);
exit (EXIT_FAILURE);
}
/* Finally, swap bytes back again, if necessary,
** so that a DUMP command will make sense.
*/
if (0x12345678 != ntohl (0x12345678)) {
switch (bpb) {
case 1: break;
case 2: for (i=0; i<n_bins; i++) p_word[i] = ntohs (p_word[i]); break;
case 4: for (i=0; i<n_bins; i++) p_long[i] = ntohl (p_long[i]);
}
}
return True;
}
/*
**==========================================================================
** Main line program
** -----------------
**==========================================================================*/
main (int argc, char *argv[]) {
/*==========================================================================*/
int i, j, k, status, is, nerr, vlen, nbins;
char *cmnd;
int bytes_to_come, bytes_to_go;
uint f_bin, n_bins, hist_num;
uint daq_was, daq_now, filler_mask, server_mask;
char recd[256], recd1[256];
char last_recd[256] = {NIL};
char *verb, *p_p1, *p_p2, *p_p3, *p_p4, *p_p5, *p_p6;
int l_recd;
XrmDatabase my_db;
char *appName;
/*============================================================================
*/
printf ("SinqHM_Client Ident \"%s\" started.\n", IDENT);
/*============================================================================
** Declare an exit handler to tidy up if we get forced to exit.
*/
is = atexit (exit_handler);
if (is != 0) {
printf ("SinqHM_Client -- error setting up exit handler.");
exit (is);
}
/*-------------------------------------------------------------
** Setup the resource database and look up the resources.
*/
Verbose = False;
for (i = 1; i < argc; i++) if (strcmp ("-v", argv[i]) == 0) Verbose = True;
setup_xrm_database (&my_db, &appName, &argc, argv, Verbose);
status = get_check_resources (&my_db, appName, &argc, argv, Verbose);
if (!status) return False;
if (argc > 1) {
printf ("\nThe following arguments were not used:\n\n ");
for (i = 1; i < argc; i++) {
printf ("\"%s\" ", argv[i]);
}
printf ("\n");
show_help (NULL);
return False;
}
/*====================================================== Wait for work =========
*/
printf ("\n"
" The following commands are available:\n"
" Help Open Status Read 2D Project Dump LOAD WRITE W2D GO STOP ZERO "
"Quit\n");
recd[0] = NIL;
printf ("> ");
while (fgets (recd, sizeof (recd), stdin) != NULL) {
nerr = 0; /* Reset error counter for each unit of work. */
if (strlen (recd) == (sizeof (recd) - 1)) {
printf ("\n\nInput buffer overflow -- command ignored!\n\n");
do { /* Flush the remains */
fgets (recd, sizeof (recd), stdin);
} while (strlen (recd) == (sizeof (recd) - 1));
printf ("> ");
continue;
}
i = strlen (recd) - 1;
if (recd[i] == NL) recd[i] = NIL; /* Suppress the trailing \n */
if (recd[0] == NIL) { /* If just <Return>, repeat */
strcpy (recd, last_recd);
}
l_recd = sizeof (recd1);
StrEdit (recd1, recd, "trim compress uncomment lowercase", &l_recd);
if (l_recd <= 0) { /* Skip empty lines */
printf ("\n> ");
continue;
}
StrJoin (recd1, sizeof (recd1), recd1, " ,,,,,,,,,,");
/*
** Parse the command
*/
verb = strtok (recd1, " \t\f\v\n");
vlen = strlen (verb);
if (StrMatch (verb, "read", 1)) {
do_1d (&verb[vlen+1], Dbg_mode); /* Generate a 1-dim plot */
}else if (StrMatch (verb, "2d", 2)) {
do_2d (&verb[vlen+1], Dbg_mode); /* Generate a 2-dim plot */
}else if (StrMatch (verb, "project", 1)) {
do_project (&verb[vlen+1], Dbg_mode); /* Do a projected read */
}else if (StrMatch (verb, "dump", 1)) {
do_dump (&verb[vlen+1]); /* Generate a dump of the data */
}else if (StrMatch (verb, "load", 4)) {
do_load (&verb[vlen+1], Dbg_mode); /* Load histog mem from file */
}else if (StrMatch (verb, "write", 5)) {
if (Rw_skt == 0) {
Rw_skt = openConnectionGbl (Rmt_host, &Rmt_port, &Pkt_size, Dbg_mode,
&Rply_buff, Verbose);
if (Rw_skt == 0) FailInet ("\nmain/openConnectionGbl error.");
}
printf ("\n Writing data to histogram memory ...");
gen_data (&verb[vlen+1]); /* Generate some pseudo data */
hist_num = -1;
f_bin = 0;
nbins = Hm_nbins * N_hists;
status = write_hm (Hm_buff_addr, hist_num, f_bin, nbins, Bytes_per_bin);
if (status) printf (" OK\n");
}else if (StrMatch (verb, "w2d", 3)) {
if (Rw_skt == 0) {
Rw_skt = openConnectionGbl (Rmt_host, &Rmt_port, &Pkt_size, Dbg_mode,
&Rply_buff, Verbose);
if (Rw_skt == 0) FailInet ("\nmain/openConnectionGbl error.");
}
printf ("\n Writing pseudo 2-dim data to histogram memory ...");
gen_data_2d (&verb[vlen+1]); /* Generate some pseudo data */
hist_num = -1;
f_bin = 0;
nbins = Hm_nbins * N_hists;
status = write_hm (Hm_buff_addr, hist_num, f_bin, nbins, Bytes_per_bin);
if (status) printf (" OK\n");
}else if (StrMatch (verb, "go", 2)) {
if (Rw_skt == 0) {
Rw_skt = openConnectionGbl (Rmt_host, &Rmt_port, &Pkt_size, Dbg_mode,
&Rply_buff, Verbose);
if (Rw_skt == 0) FailInet ("\nmain/openConnectionGbl error.");
}
printf ("\n Starting data acquisition ...");
/*
** Send the request message
*/
Req_buff.bigend = htonl (0x12345678);
Req_buff.cmnd = htonl (SQHM_DAQ);
Req_buff.u.daq.sub_cmnd = htonl (DAQ__GO);
status = send (Rw_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
if (status == -1) FailInet ("SinqHM_Client -- R/W-Socket send error\n");
if (status != sizeof (Req_buff)) {
printf ("\n"
"SinqHM_Client -- wrong number of bytes sent: %d", status);
exit (EXIT_FAILURE);
}
/*
** Now get the server's status message.
*/
status = recv (Rw_skt, (char *) &Rply_buff, sizeof (Rply_buff), 0);
if (status == -1) {
FailInet ("\nSinqHM_Client -- R/W-Socket recv error\n");
exit (EXIT_FAILURE);
}else if (status != sizeof (Rply_buff)) {
printf ("\n"
"SinqHM_Client -- Cnct-Socket recv error - "
"unexpected byte count: %d.\n", status);
exit (EXIT_FAILURE);
}
if (ntohl (Rply_buff.bigend) != 0x12345678) {
printf ("\n"
"SinqHM_Client -- big-endian/little-endian problem!\n"
" Buffer received in non-network byte order!\n");
exit (EXIT_FAILURE);
}else if (ntohl (Rply_buff.status) != KER__SUCCESS) {
printf ("\n"
"SinqHM_Client -- Bad status from Go Request: %d.\n",
ntohl (Rply_buff.status));
printf (" \"%s\"\n", Rply_buff.u.message);
exit (EXIT_FAILURE);
}else {
daq_was = ntohs (Rply_buff.u.daq.daq_was);
daq_now = ntohs (Rply_buff.u.daq.daq_now);
filler_mask = ntohs (Rply_buff.u.daq.filler_mask);
server_mask = ntohs (Rply_buff.u.daq.server_mask);
if (daq_now == 0) {
printf (" OK.\n");
if (daq_was == 0)
printf (" Actually, data acquisition was already active.\n");
}else {
printf ("\n"
" Data acquisition not yet started. The various masks"
" are:\n"
" Daq-state-now = 0x%04x\n"
" Filler-mask = 0x%04x\n"
" Server-mask = 0x%04x\n",
daq_now, filler_mask, server_mask);
}
}
}else if ((StrMatch (verb, "show", 1)) ||
(StrMatch (verb, "status", 1))) {
do_status (Dbg_mode); /* Get status of SinqHM_srv */
}else if (StrMatch (verb, "stop", 4)) {
if (Rw_skt == 0) {
Rw_skt = openConnectionGbl (Rmt_host, &Rmt_port, &Pkt_size, Dbg_mode,
&Rply_buff, Verbose);
if (Rw_skt == 0) FailInet ("\nmain/openConnectionGbl error.");
}
printf ("\n Stopping data acquisition ...");
/*
** Send the request message
*/
Req_buff.bigend = htonl (0x12345678);
Req_buff.cmnd = htonl (SQHM_DAQ);
Req_buff.u.daq.sub_cmnd = htonl (DAQ__STOP);
status = send (Rw_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
if (status == -1) FailInet ("\nmain/send -- R/W-Socket send error\n");
if (status != sizeof (Req_buff)) {
printf ("\n"
"SinqHM_Client -- wrong number of bytes sent: %d", status);
exit (EXIT_FAILURE);
}
/*
** Now get the server's status message.
*/
status = recv (Rw_skt, (char *) &Rply_buff, sizeof (Rply_buff), 0);
if (status == -1) {
FailInet ("\nmain/recv -- R/W-Socket recv error\n");
exit (EXIT_FAILURE);
}else if (status != sizeof (Rply_buff)) {
printf ("\n"
"SinqHM_Client -- Cnct-Socket recv error - "
"unexpected byte count: %d.\n", status);
exit (EXIT_FAILURE);
}
if (ntohl (Rply_buff.bigend) != 0x12345678) {
printf ("\n"
"SinqHM_Client -- big-endian/little-endian problem!\n"
" Buffer received in non-network byte order!\n");
exit (EXIT_FAILURE);
}else if (ntohl (Rply_buff.status) != KER__SUCCESS) {
printf ("\n"
"SinqHM_Client -- Bad status from Stop Request: %d.\n",
ntohl (Rply_buff.status));
printf (" \"%s\"\n", Rply_buff.u.message);
exit (EXIT_FAILURE);
}else {
daq_was = ntohs (Rply_buff.u.daq.daq_was);
daq_now = ntohs (Rply_buff.u.daq.daq_now);
filler_mask = ntohs (Rply_buff.u.daq.filler_mask);
server_mask = ntohs (Rply_buff.u.daq.server_mask);
if (daq_now != 0) {
printf (" OK. The various masks are:\n"
" Daq-state-now = 0x%04x\n"
" Filler-mask = 0x%04x\n"
" Server-mask = 0x%04x\n",
daq_now, filler_mask, server_mask);
}else {
printf ("\n"
" Data acquisition is still active!\n");
}
}
}else if (StrMatch (verb, "zero", 4)) {
if (Rw_skt == 0) {
Rw_skt = openConnectionGbl (Rmt_host, &Rmt_port, &Pkt_size, Dbg_mode,
&Rply_buff, Verbose);
if (Rw_skt == 0) FailInet ("\nmain/openConnectionGbl error.");
}
p_p1 = strtok (NULL, " \t,"); /* Get pointers to the 2 args */
p_p2 = strtok (NULL, " \t,");
if ((p_p1 != NULL) && (sscanf (p_p1, "%d", &f_bin) == 1)) {
if (p_p2 != NULL) {
if (sscanf (p_p2, "%d", &n_bins) != 1) n_bins = Hm_nbins;
}
}else {
f_bin = 0;
n_bins = Hm_nbins * N_hists;
}
printf ("\n Zeroing histogram memory ...\n"
" First bin = %d\n"
" # bins = %d\n", f_bin, n_bins);
/*
** Send the request message first
*/
Req_buff.bigend = htonl (0x12345678);
Req_buff.cmnd = htonl (SQHM_ZERO);
Req_buff.u.zero.hist_no = htonl (-1);
Req_buff.u.zero.first_bin = htonl (f_bin);
Req_buff.u.zero.n_bins = htonl (n_bins);
status = send (Rw_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
if (status == -1) FailInet ("\nmain/send -- R/W-Socket send error\n");
if (status != sizeof (Req_buff)) {
printf ("SinqHM_Client -- wrong number of bytes sent: %d", status);
exit (EXIT_FAILURE);
}
/*
** Now get the server's status message.
*/
status = recv (Rw_skt, (char *) &Rply_buff, sizeof (Rply_buff), 0);
if (status == -1) {
FailInet ("\nmain/recv -- R/W-Socket recv error\n");
exit (EXIT_FAILURE);
}else if (status != sizeof (Rply_buff)) {
printf ("SinqHM_Client -- Cnct-Socket recv error - ");
printf ("unexpected byte count: %d.\n", status);
exit (EXIT_FAILURE);
}
if (ntohl (Rply_buff.bigend) != 0x12345678) {
printf (
"SinqHM_Client -- big-endian/little-endian problem!\n"
" Buffer received in non-network byte order!\n");
exit (EXIT_FAILURE);
}else if (ntohl (Rply_buff.status) != KER__SUCCESS) {
printf ("SinqHM_Client -- Bad status from Zero Request: %d.\n",
ntohl (Rply_buff.status));
printf (" \"%s\"\n", Rply_buff.u.message);
exit (EXIT_FAILURE);
}else {
printf (" done.\n");
}
}else if ((StrMatch (verb, "open", 1)) ||
(StrMatch (verb, "connect", 1))) {
if (Rw_skt == 0) {
printf ("\n Opening the connection ...\n");
Rw_skt = openConnectionGbl (Rmt_host, &Rmt_port, &Pkt_size, Dbg_mode,
&Rply_buff, Verbose);
if (Rw_skt == 0) FailInet ("\nmain/openConnection error.");
}else {
printf ("\n The connection is already open!\n");
}
}else if ((StrMatch (verb, "exit", 1)) ||
(StrMatch (verb, "quit", 1)) ||
(StrMatch (verb, "end", 1))) {
break;
}else if ((StrMatch (verb, "?", 1)) ||
(StrMatch (verb, "help", 1))) {
show_help (strtok (NULL, " \t,"));
}else {
printf (" Illegal command - type \"?\" for help.\n");
}
strcpy (last_recd, recd);
/*
** Get another command.
*/
printf ("> ");
}
/*
** Time to quit. Note that the exit handler will tidy
** up any open connection to the Hist Mem Server,
*/
exit (EXIT_SUCCESS);
}
/*============================================= End of SinqHM_Client.C ======*/