diff options
author | Joe Hunkeler <jhunkeler@gmail.com> | 2015-08-11 16:51:37 -0400 |
---|---|---|
committer | Joe Hunkeler <jhunkeler@gmail.com> | 2015-08-11 16:51:37 -0400 |
commit | 40e5a5811c6ffce9b0974e93cdd927cbcf60c157 (patch) | |
tree | 4464880c571602d54f6ae114729bf62a89518057 /unix/sun/fifo.c | |
download | iraf-osx-40e5a5811c6ffce9b0974e93cdd927cbcf60c157.tar.gz |
Repatch (from linux) of OSX IRAF
Diffstat (limited to 'unix/sun/fifo.c')
-rw-r--r-- | unix/sun/fifo.c | 759 |
1 files changed, 759 insertions, 0 deletions
diff --git a/unix/sun/fifo.c b/unix/sun/fifo.c new file mode 100644 index 00000000..65471a77 --- /dev/null +++ b/unix/sun/fifo.c @@ -0,0 +1,759 @@ +/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + */ + +#include <sys/types.h> +#include <sys/time.h> +#include <sys/file.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <signal.h> +#include <ctype.h> +#include <stdio.h> + +#define SUNOS4 + +/* + * FIFO.C -- Test fifo i/o. This is a server process much like IMTOOL, + * except that all the process does is respond to datastream requests + * to read and write an internal 512 sq frame buffer maintained as an + * array in memory (only one frame buffer is supported). A log is kept + * to the stderr of all datastream requests. + * + * Used to debug fifo i/o - NOT USED IN THE ONLINE PROGRAMS. + * + * To make: cc fifo.c -o fifo.e + * + * Usage: fifo.e >& spool run server, logging output to spool + * fifo.e -i run interactively + * + * In interactive mode, cursor value strings may be typed in on the fifo.e + * stdin in response to cursor read requests from the client. Otherwise, + * a constant cursor value "1.0 1.0 101 q" is returned. + */ + +#define I_DEVNAME "/dev/imt1o" +#define O_DEVNAME "/dev/imt1i" +#define OLD_DEVNAME "/dev/imt1" +#define IO_TIMEOUT 30 +#define SZ_FIFOBUF 4000 +#define SZ_WCSBUF 320 /* WCS text buffer size */ +#define MAX_FRAMES 1 +#define SZ_FNAME 256 + +#define MEMORY 01 /* frame buffer i/o */ +#define LUT 02 /* lut i/o */ +#define FEEDBACK 05 /* used for frame clears */ +#define IMCURSOR 020 /* logical image cursor */ +#define WCS 021 /* used to set WCS */ + +#define SZ_IMCURVAL 160 +#define PACKED 0040000 +#define COMMAND 0100000 +#define IIS_READ 0100000 +#define IMC_SAMPLE 0040000 +#define IMT_FBCONFIG 077 + +struct iism70 { + short tid; + short thingct; + short subunit; + short checksum; + short x, y, z; + short t; +}; + +#ifndef abs +#define abs(a) (((a)<0)?(-a):(a)) +#endif + +#ifndef min +#define min(a,b) ((a)<(b)?(a):(b)) +#endif +#ifndef max +#define max(a,b) ((a)<(b)?(b):(a)) +#endif + +static int interactive=0; +static int background=0; +static int datain, dataout=0; +static char framebuf[512*512]; +static int frame=1, reference_frame=1, display_frame=1; +static int fb_config_index=1, fb_nframes=1; +static int Fb_width = 512, Fb_height = 512; +static char wcsbuf[MAX_FRAMES][SZ_WCSBUF]; + + +/* FIFO -- Text fifo i/o. + */ +main (argc, argv) +int argc; +char **argv; +{ + fd_set fds; + + if (argc > 1) + if (strcmp (argv[1], "-i") == 0) + interactive++; /* type in cursor values */ + + /* Open the output fifo. We have to open it ourselves first as a + * client to get around the fifo open-no-client error. + */ + if ((datain = open (O_DEVNAME, O_RDONLY|O_NDELAY)) != -1) { + if ((dataout = open (O_DEVNAME, O_WRONLY|O_NDELAY)) != -1) + fcntl (dataout, F_SETFL, O_WRONLY); + close (datain); + } + + /* Open the input stream, a FIFO pseudodevice file used by + * applications to send us commands and data. + */ + if ((datain = open (I_DEVNAME, O_RDONLY|O_NDELAY)) == -1) { + if ((datain = open (OLD_DEVNAME, O_RDONLY|O_NDELAY)) == -1) + fprintf (stderr, "Warning: cannot open %s\n", I_DEVNAME); + } else { + /* Clear O_NDELAY for reading. */ + fcntl (datain, F_SETFL, O_RDONLY); + } + + FD_ZERO (&fds); FD_SET (datain, &fds); + while (select (FD_SETSIZE, &fds, NULL, NULL, NULL) > 0) { + ev_cmdinput(); + fflush (stdout); + fflush (stderr); + FD_ZERO (&fds); FD_SET (datain, &fds); + } + + close (datain); + exit (0); +} + + +/* EV_CMDINPUT -- Called when command or data input has arrived via the + * pseudodevice input stream from some applications process. + */ +ev_cmdinput() +{ + register unsigned char *cp; + register int sum, i; + register short *p; + int ndatabytes, nbytes, n, ntrys=0; + static int errmsg=0, bswap=0; + struct iism70 iis; + char buf[SZ_FIFOBUF]; + int fb_index; + + /* Get the IIS header. */ + if (read (datain, (char *)&iis, sizeof(iis)) < sizeof(iis)) { + fprintf (stderr, "imtool: command input read error\n"); + fflush (stderr); + return (0); + } else if (bswap) + bswap2 ((char *)&iis, (char *)&iis, sizeof(iis)); + + /* Verify the checksum. If it fails swap the bytes and try again. + */ + for (;;) { + for (i=0, sum=0, p=(short *)&iis; i < 8; i++) + sum += *p++; + if ((sum & 0177777) == 0177777) + break; + + if (ntrys++) { + if (!errmsg++) { + fprintf (stderr, "imtool: bad data header checksum\n"); + fflush (stderr); + if (bswap) + bswap2 ((char *)&iis, (char *)&iis, sizeof(iis)); + fprintf (stderr, "noswap:"); + for (i=0, p=(short *)&iis; i < 8; i++) + fprintf (stderr, " %6o", p[i]); + fprintf (stderr, "\n"); + + bswap2 ((char *)&iis, (char *)&iis, sizeof(iis)); + fprintf (stderr, " swap:"); + for (i=0, p=(short *)&iis; i < 8; i++) + fprintf (stderr, " %6o", p[i]); + fprintf (stderr, "\n"); + fflush (stderr); + } + break; + + } else { + bswap2 ((char *)&iis, (char *)&iis, sizeof(iis)); + bswap = !bswap; + } + } + + ndatabytes = -iis.thingct; + if (!(iis.tid & PACKED)) + ndatabytes *= 2; + + /* Log command. */ + fprintf (stderr, + "subunit=%06o tid=%06o nbytes=%7d x=%06o y=%06o z=%06o\n", + iis.subunit & 077, + iis.tid, + ndatabytes, + iis.x & 0177777, + iis.y & 0177777, + iis.z & 0177777); + fflush (stderr); + + switch (iis.subunit & 077) { + case FEEDBACK: + /* The feedback unit is used only to clear a frame. + */ + set_reference_frame (decode_frameno (iis.z & 07777)); + /* erase (rf_p); */ + fprintf (stderr, "erase frame %d\n", reference_frame); + break; + + case LUT: + /* Data mode writes to the frame lookup tables are not implemented. + * A command mode write to the LUT subunit is used to connect + * image memories up to the RGB channels, i.e., to select the frame + * to be displayed. We ignore any attempt to assign multiple + * frames to multiple color channels, and just do a simple frame + * select. + */ + if (iis.subunit & COMMAND) { + int frame, z, n; + short x[14]; + + if (read (datain, (char *)x, ndatabytes) == ndatabytes) { + if (bswap) + bswap2 ((char *)x, (char *)x, ndatabytes); + + z = x[0]; + if (!z) z = 1; + for (n=0; !(z & 1); z >>= 1) + n++; + + frame = max (1, n + 1); + if (frame > fb_nframes) { + if (frame < MAX_FRAMES) { + /* set_fbconfig (fb_config_index, frame); */ + fprintf (stderr, "set_fbconfig (%d, %d)\n", + fb_config_index, frame); + } else { + fprintf (stderr, "imtool warning: "); + fprintf (stderr, + "attempt to display nonexistent frame %d\n", frame); + frame = fb_nframes - 1; + } + } + + /* set_frame (frame); */ + fprintf (stderr, "set_frame (%d)\n", frame); + return (0); + } + } + + case MEMORY: + /* Load data into the frame buffer. Data is assumed to be byte + * packed. + */ + if (iis.tid & IIS_READ) { + /* Read from the display. + */ + unsigned char *fb, *ip; + int nbytes, nleft, n, x, y; + long starttime; + + /* Get the frame to be read from. */ + set_reference_frame (decode_frameno (iis.z & 07777)); + + fb = (unsigned char *)framebuf; + nbytes = ndatabytes; + x = iis.x & 01777; + y = iis.y & 01777; + + ip = max (fb, min (fb + Fb_width * Fb_height - nbytes, + fb + y * Fb_width + x)); + if (ip != fb + y * Fb_width + x) { + fprintf (stderr, + "imtool: attempted read out of bounds on framebuf\n"); + fprintf (stderr, + "read %d bytes at [%d,%d]\n", nbytes, x, y); + } + + /* Log i/o command. */ + fprintf (stderr, "read %d bytes at x=%d, y=%d\n", + nbytes, x, y); + + /* Return the data from the frame buffer. */ + starttime = time(0); + for (nleft = nbytes; nleft > 0; nleft -= n) { + n = (nleft < SZ_FIFOBUF) ? nleft : SZ_FIFOBUF; + if ((n = write (dataout, ip, n)) <= 0) { + if (n < 0 || (time(0) - starttime > IO_TIMEOUT)) { + fprintf (stderr, "IMTOOL: timeout on write\n"); + break; + } + } else + ip += n; + } + + return (0); + + } else { + /* Write to the display. + */ + unsigned char *fb, *op; + int nbytes, nleft, n, x, y; + long starttime; + + /* Get the frame to be written into (encoded with a bit for + * each frame, 01 is frame 1, 02 is frame 2, 04 is frame 3, + * and so on). + */ + set_reference_frame (decode_frameno (iis.z & 07777)); + + /* Get a pointer into the frame buffer where the data will + * be put. + */ + fb = (unsigned char *)framebuf; + nbytes = ndatabytes; + x = iis.x & 07777; + y = iis.y & 07777; + + op = max (fb, min (fb + Fb_width * Fb_height - nbytes, + fb + y * Fb_width + x)); + if (op != fb + y * Fb_width + x) { + fprintf (stderr, + "imtool: attempted write out of bounds on framebuf\n"); + fprintf (stderr, + "write %d bytes to [%d,%d]\n", nbytes, x, y); + } + + /* Log i/o command. */ + fprintf (stderr, "write %d bytes at x=%d, y=%d\n", + nbytes, x, y); + + /* Read the data into the frame buffer. + */ + starttime = time(0); + for (nleft = nbytes; nleft > 0; nleft -= n) { + n = (nleft < SZ_FIFOBUF) ? nleft : SZ_FIFOBUF; + if ((n = read (datain, op, n)) <= 0) { + if (n < 0 || (time(0) - starttime > IO_TIMEOUT)) + break; + } else { + /* Set any zeroed pixels to the background color, + * if a special background color is specified. + */ + if (background) + for (cp=op, i=n; --i >= 0; cp++) + if (!*cp) + *cp = background; + op += n; + } + } + + /* Refresh the display, if the current display frame is the + * same as the reference frame. + if (rf_p == df_p) { + BRect fb_r, pw_r; + + fb_r.r_left = x * zoom; + fb_r.r_top = y * zoom; + fb_r.r_width = min (nbytes * zoom, fb_width); + fb_r.r_height = ((nbytes*zoom*zoom + fb_width-1)/fb_width); + + Bpw_get_region_rect (gio_pw, &pw_rect); + Bpw_lock (gio_pw, &pw_rect); + + pw_rect.r_left = df_p->fb_xoff; + pw_rect.r_top = df_p->fb_yoff; + + if (maprect (&fb_rect, &fb_r, &pw_rect, &pw_r)) + if (maprect (&pw_rect, &pw_r, &fb_rect, &fb_r)) { + ds_write (gio_pw, + pw_r.r_left, pw_r.r_top, + pw_r.r_width, pw_r.r_height, + PIX_SRC | PIX_COLOR(NGREY-1), + df_p->fb_pr, fb_r.r_left, fb_r.r_top); + + if (pw_r.r_top + pw_r.r_height >= pw_rect.r_height + - cb_height) + put_colorbar(); + } + + Bpw_unlock (gio_pw); + } + */ + + return (0); + } + break; + + case WCS: + /* Read or write the WCS for a frame. The frame number to + * which the WCS applies is passed in Z and the frame buffer + * configuration in T. The client changes the frame buffer + * configuration in a WCS set. The WCS text follows the header + * as byte packed ASCII data. + */ + if (iis.tid & IIS_READ) { + /* Return the WCS for the referenced frame. + */ + register char *op; + register int n; + char emsg[SZ_WCSBUF]; + char *text; + int frame; + + for (op=emsg, n=SZ_WCSBUF; --n >=0; ) + *op++ = 0; + + frame = decode_frameno (iis.z & 07777); + if (frame > fb_nframes) + strcpy (text=emsg, "[NOSUCHFRAME]\n"); + else { + set_reference_frame (frame); + text = wcsbuf[reference_frame-1]; + } + + fprintf (stderr, "query wcs:\n"); + write (2, text, SZ_WCSBUF); + + write (dataout, text, SZ_WCSBUF); + + } else { + /* Set the WCS for the referenced frame. + */ + char buf[1024]; + int fb_config, frame; + + frame = decode_frameno (iis.z & 07777); + if (frame > fb_nframes) + if (frame < MAX_FRAMES) { + /* set_fbconfig (fb_config_index, frame); */ + fprintf (stderr, "set_fbconfig (%d, %d)\n", + fb_config_index, frame); + } + + set_reference_frame (frame); + if ((fb_config = iis.t & 077) != fb_config_index) { + /* set_fbconfig (fb_config_index, frame); */ + fprintf (stderr, "set_fbconfig (%d, %d)\n", + fb_config_index, frame); + } + + /* Read in and set up the WCS. */ + if (read (datain, buf, ndatabytes) == ndatabytes) + strncpy (wcsbuf[reference_frame-1], buf, SZ_WCSBUF); + + fprintf (stderr, "set wcs:\n"); + write (2, buf, SZ_WCSBUF); + + /* + strcpy (rf_p->fb_ctran.format, W_DEFFORMAT); + rf_p->fb_ctran.imtitle[0] = '\0'; + rf_p->fb_ctran.valid = 0; + rf_p->fb_imageno++; + rf_p->fb_objno = 1; + + wcs_update (rf_p); + if (rf_p == df_p) + window_set (gio_frame, FRAME_LABEL, framelabel(), 0); + */ + } + + return (0); + break; + + case IMCURSOR: + /* Read or write the logical image cursor. This is an extension + * added to provide a high level cursor read facility; this is + * not the same as a low level access to the IIS cursor subunit. + * Cursor reads may be either nonblocking (immediate) or blocking, + * using the keyboard or mouse to terminate the read, and + * coordinates may be returned in either image (world) or frame + * buffer pixel coordinates. + */ + if (iis.tid & IIS_READ) { + /* Read the logical image cursor. In the case of a blocking + * read all we do is initiate a cursor read; completion occurs + * when the user hits a key or button. + */ + fprintf (stderr, "read cursor position\n"); + if (iis.tid & IMC_SAMPLE) { + /* Sample the cursor position. */ + /* + register struct ctran *ct; + int wcs = iis.z; + int sx, sy; + float wx, wy; + + wx = sx = last_x + pw_rect.r_left; + wy = sy = last_y + pw_rect.r_top; + + if (wcs) { + ct = wcs_update (df_p); + if (ct->valid) { + if (abs(ct->a) > .001) + wx = ct->a * sx + ct->c * sy + ct->tx; + if (abs(ct->d) > .001) + wy = ct->b * sx + ct->d * sy + ct->ty; + } + } + */ + + int wcs = iis.z, key = 'q'; + float wx=1.0, wy=1.0; + + /* Return the cursor value on the output datastream encoded + * in a fixed size ascii buffer. + */ + gio_retcursorval (wx, wy, display_frame*100+wcs, key, ""); + + } else { + /* Initiate a user triggered cursor read. */ + /* gio_readcursor (iis.z); */ + int wcs = iis.z, key = 'q'; + float wx=1.0, wy=1.0; + gio_retcursorval (wx, wy, display_frame*100+wcs, key, ""); + } + + } else { + /* Write (set) the logical image cursor position. */ + /* + fprintf (stderr, "write cursor position\n"); + register struct ctran *ct; + int sx = iis.x, sy = iis.y; + float wx = sx, wy = sy; + int wcs = iis.z; + + if (wcs) { + ct = wcs_update (df_p); + if (ct->valid) { + if (abs(ct->a) > .001) + sx = (wx - ct->tx) / ct->a; + if (abs(ct->d) > .001) + sy = (wy - ct->ty) / ct->d; + } + } + + gio_setcursorpos (sx - pw_rect.r_left, sy - pw_rect.r_top); + */ + } + + return (0); + break; + + default: + /* Ignore unsupported command input. + */ + break; + } + + /* Discard any data following the header. */ + if (!(iis.tid & IIS_READ)) + for (nbytes = ndatabytes; nbytes > 0; nbytes -= n) { + n = (nbytes < SZ_FIFOBUF) ? nbytes : SZ_FIFOBUF; + if ((n = read (datain, buf, n)) <= 0) + break; + } + + fflush (stderr); + return (0); +} + + +/* SET_REFERENCE_FRAME -- Set reference frame. If the frame referenced is + * greater than the current number of frames, attempt to increase the number + * of frames. + */ +static +set_reference_frame (n) +register int n; +{ + reference_frame = max (1, n); + if (reference_frame > fb_nframes) { + if (reference_frame < MAX_FRAMES) { + /* set_fbconfig (fb_config_index, reference_frame); */ + fprintf (stderr, "set_fbconfig %d %d\n", + fb_config_index, reference_frame); + } else { + fprintf (stderr, "imtool warning: "); + fprintf (stderr, + "attempt to reference nonexistent frame %d\n", + reference_frame); + reference_frame = fb_nframes; + } + } + + /* rf_p = frames + (reference_frame - 1); */ +} + + +/* DECODE_FRAMENO -- Decode encoded IIS register frame number. + */ +static +decode_frameno (z) +register int z; +{ + register int n; + + /* Get the frame number, encoded with a bit for each frame, 01 is + * frame 1, 02 is frame 2, 04 is frame 3, and so on. + */ + if (!z) z = 1; + for (n=0; !(z & 1); z >>= 1) + n++; + + return (max (1, n + 1)); +} + + +/* BSWAP2 - Move bytes from array "a" to array "b", swapping successive + * pairs of bytes. The two arrays may be the same but may not be offset + * and overlapping. + */ +static +bswap2 (a, b, nbytes) +char *a, *b; /* input array */ +int nbytes; /* number of bytes to swap */ +{ + register char *ip=a, *op=b, *otop; + register unsigned temp; + + /* Swap successive pairs of bytes. + */ + for (otop = op + (nbytes & ~1); op < otop; ) { + temp = *ip++; + *op++ = *ip++; + *op++ = temp; + } + + /* If there is an odd byte left, move it to the output array. + */ + if (nbytes & 1) + *op = *ip; +} + + +/* GIO_RETCURSORVAL -- Return the cursor value on the output datastream to + * the client which requested the cursor read. + */ +static +gio_retcursorval (wx, wy, wcs, key, strval) +float wx, wy; /* cursor coordinates */ +int wcs; /* encoded WCS value */ +int key; /* keystroke used as trigger */ +char *strval; /* optional string value */ +{ + register char *op; + register int n; + char curval[SZ_IMCURVAL]; + char keystr[20]; + + for (op=curval, n=SZ_IMCURVAL; --n >=0; ) + *op++ = 0; + + /* If running FIFO in interactive mode, allow the user to type + * in the cursor value on the standard input. + */ + if (interactive) { + fprintf (stderr, "enter cursor value string: "); + fflush (stderr); + if (fgets (curval, SZ_IMCURVAL, stdin) != NULL) + goto ret; + } + + /* Encode the cursor value. */ + if (key == EOF) + sprintf (curval, "EOF\n"); + else { + if (isprint (key) && !isspace(key)) { + keystr[0] = key; + keystr[1] = '\0'; + } else + sprintf (keystr, "\\%03o", key); + + sprintf (curval, "%10.3f %10.3f %d %s %s\n", + wx, wy, wcs, keystr, strval); + } +ret: + fprintf (stderr, "%s", curval); + + /* Send it to the client program. */ + write (dataout, curval, sizeof(curval)); +} + + +#define mask(s) (1<<((s)-1)) +#define setvec(vec, a) \ + vec.sv_handler = a; vec.sv_mask = vec.sv_onstack = 0 + +static int ringring; + + +/* WMSEC -- Suspend task execution (sleep) for the specified number + * of milliseconds. + */ +wmsec (msec) +int msec; +{ + struct itimerval itv, oitv; + register struct itimerval *itp = &itv; + struct sigvec vec, ovec; +#ifdef SUNOS4 + void napmsx(); +#else + int napmsx(); +#endif + int omask; + + if (msec == 0) + return; + + timerclear (&itp->it_interval); + timerclear (&itp->it_value); + if (setitimer (ITIMER_REAL, itp, &oitv) < 0) + return; + + setvec (ovec, SIG_DFL); + omask = sigblock(0); + + itp->it_value.tv_usec = (msec * 1000) % 1000000; + itp->it_value.tv_sec = (msec * 1000) / 1000000; + + if (timerisset (&oitv.it_value)) { + if (timercmp(&oitv.it_value, &itp->it_value, >)) + oitv.it_value.tv_sec -= itp->it_value.tv_sec; + else { + itp->it_value = oitv.it_value; + /* This is a hack, but we must have time to + * return from the setitimer after the alarm + * or else it'll be restarted. And, anyway, + * sleep never did anything more than this before. + */ + oitv.it_value.tv_sec = 1; + oitv.it_value.tv_usec = 0; + } + } + + setvec (vec, napmsx); + (void) sigvec (SIGALRM, &vec, &ovec); + ringring = 0; + (void) setitimer (ITIMER_REAL, itp, (struct itimerval *)0); + + while (!ringring) + sigpause (omask &~ mask(SIGALRM)); + + (void) sigvec (SIGALRM, &ovec, (struct sigvec *)0); + (void) setitimer (ITIMER_REAL, &oitv, (struct itimerval *)0); +} + + +#ifdef SUNOS4 +static void +#else +static int +#endif +napmsx() +{ + ringring = 1; +} |