diff --git a/sinqhm/sinqhm_client.c b/sinqhm/sinqhm_client.c new file mode 100755 index 00000000..28104b1a --- /dev/null +++ b/sinqhm/sinqhm_client.c @@ -0,0 +1,3116 @@ +#define IDENT "1C05" +/*---------------------------------------------------------------------------*/ +#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 +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifdef __VMS +#include +#else +#include +#endif +/* +**==================== Global Definitions ===================================== +*/ +#include + +#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 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_project/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]; + char dev[] = "/XW"; + 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. +*/ + 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 (" is invalid: \"%s\"\n", p_p6); + printf (" 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 (" 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 (" 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 (" 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]; + char dev[] = "/XW"; + 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 . +*/ + 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" + " ? \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> \n" + " ^ ^ ^\n" + " | | |\n" + " | | +--- Dflt = -1\n" + " | +------------ Dflt = see below\n" + " +--------------------- Dflt = 0\n" + "\n" + " Read <#-bins> bins starting at <1st-bin> of histogram .\n" + "\n" + " If is -1, the histogram data is regarded as a single " + "histogram.\n" + " The default for <#-bins> depends on the value of . " + "If \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" + " , <-- \"X\" or \"Y\" for proj'n onto x- or " + "y-axis. Dflt = \"X\".\n" + " , <-- gives x-extent of histog in pseudo-2-" + "dim mode.\n" + " <-- 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 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> \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 \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 \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" + " ... .\n" + "\n"); + }else if (StrMatch (token, "w2d", 2)) { + printf ("\n" + " WRITE <#-hists> \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" + " ... .\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 \" \"\n" + " setenv SINQHM_DBG_MODE \n" + "\n" + " The following logical names should be set on VMS systems:\n" + "\n" + " DEFINE/GROUP SINQHM_FRONTEND \" \"\n" + " DEFINE/GROUP SINQHM_DBG_MODE \n" + "\n" + " Defaults:\n" + " None 0\n" + " 2400\n" + " 8192\n" + "\n" + " If 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 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 ("SinqHM_Client -- 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 ("SinqHM_Client -- 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 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 , 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) write (" 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 ("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 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 ("SinqHM_Client -- 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 ("SinqHM_Client -- 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 ======*/