/*----------------------------------------------------------------*/ /* varread.c Keven Miller 25 Jan 2010 */ #ifdef __mpexl #pragma list off #pragma LOCALITY "3kRanger" #endif /*----------------------------------------------------------------*/ /* Read VAR records from var-rec file */ /* Make: setvar ccopts -Aa +e +w1 */ /* ccxllk varread.c, varread.pub */ /* */ /* -- Non-destructive read of message file -- */ /* Using the COPY mode in FOPEN allows non-destructive reading */ /* of message files. But requires exclusive access to the file. */ /* */ /* -- Echo control for READX -- */ /* File number 0 is STDINX on NMPRGs. Use Fcontrol 13,12 to */ /* disable/enable echo; Use Fsetmode to disable/enable echo of */ /* newline. */ /* */ /* -- Control-Y interrupt of FREAD -- */ /* I thought that Control-Y would interrupt FREAD. Maybe on MPE/V.*/ /* To do so for NMPRGs, you need to use NoWait IO, and the IOWAIT */ /* intrinsic. You cannot do COPY with NOWAIT. */ /* */ /*------------------------------------------------------------------ 04/06/2011 1.01 KDM Added sw_delay - secs between records 04/06/2011 1.02 KDM Added hit-a-key to continue if delay=0 04/07/2011 1.03 KDM Added -w Wait if writers exist; disable echo when delay = keypress 04/07/2011 1.04 KDM Added IOWAIT (nowait io) to enhance Control-Y ------------------------------------------------------------------*/ #include /* printf sprintf fprintf */ #include /* strchr memset strcat */ #include /* atoi */ #ifdef __mpexl /* --- MPE --- */ #pragma intrinsic CCODE #pragma intrinsic FCHECK #pragma intrinsic FCLOSE #pragma intrinsic FCONTROL #pragma intrinsic FERRMSG #pragma intrinsic FFILEINFO #pragma intrinsic FOPEN #pragma intrinsic FREAD #pragma intrinsic IOWAIT #pragma intrinsic PRINT #pragma intrinsic READX #pragma intrinsic RESETCONTROL #pragma intrinsic XCONTRAP #ifndef RNG_S16 #define RNG_S16 typedef short s16; typedef unsigned short u16; typedef int s32; typedef unsigned int u32; typedef float f32; typedef double f64; #endif # define NOARG , # define XFXMASK # define XFXMASKSET(n) # define MPE_INIT() # define MPE_FINISH() #else /* --- Transport --- */ # include "transport.h" # define NOARG # define XFXMASK &xfxmask, # define XFXMASKSET(n) (xfxmask = n) u32 xfxmask; #endif /* --- --- --- */ #ifdef __GNUC__ # define RNG_GCC_UNUSED __attribute__((__unused__)) #else # define RNG_GCC_UNUSED #endif #define SETVER(x,n) static char _id_ ## n [] RNG_GCC_UNUSED = \ "@(#) " __DATE__ " " __TIME__ " " x " " #n extern u32 sleep ( u32 ); int vfn; /*----------------------------------------------------------------*/ #define proc #define VERSION "E.01.04" #define MAX_BUF 32760 #define CCE 2 #define CCL 1 #define CCG 0 #define SW_DATA 0x0001 /* -d */ #define SW_TRIM 0x0002 /* -t */ #define SW_BOTH 0x0004 /* -b */ #define SW_DEST 0x0010 /* -r */ #define SW_WAIT 0x0020 /* -w */ #define SW_DELY 0x0040 /* -s 0-32767 */ SETVER ( VERSION, varread_file ); /*----------------------------------------------------------------*/ int cy; proc int trapcy (void) { s16 sp; ++cy; fprintf ( stderr, "\n\a!! Control-Y !!\n\n" ); FCONTROL ( vfn, 43, &sp ); RESETCONTROL (); return cy; } /*----------------------------------------------------------------*/ proc int trapcy_set (void) { int rtv, old, cc; rtv = 0; XCONTRAP ( (int) &trapcy, &old ); cc = CCODE (); if ( cc == CCE ) { rtv = 1; fprintf ( stderr, "!! Control-Y Enabled\n" ); } return rtv; } /*----------------------------------------------------------------*/ /* return 3 = ascii data */ /* 2 = ascii data with bell,backspace,tab,newline,return */ /* 1 = ascii data with escape */ /* 0 = binary data */ proc int print_chk ( char *buf, int len ) { int typ, x; typ = 3; for ( x = 0; x < len; ++x, ++buf ) { if ( ' ' <= *buf && *buf <= '~' ) continue; typ = 2; if ( *buf && strchr ( "\a\b\t\n\r", *buf )) continue; typ = 1; if ( '\033' == *buf ) continue; typ = 0; break; } return typ; } /*----------------------------------------------------------------*/ /* eno = 0: FCHECK and print errmsg */ /* -1: FCHECK only */ /* eno = +n: print errmsg */ proc int fserr_get ( int fno, int eno, char *loc ) { s16 myerr, mylen; char msg [80]; /* Get fserr */ myerr = eno; if ( eno <= 0 ) { FCHECK ( fno, &myerr ); if ( CCE != CCODE () ) myerr = 72; /* Invalid File Number */ } /* Display fserr */ if ( eno >= 0 ) { FERRMSG ( &myerr, msg, &mylen ); if ( CCE != CCODE () ) mylen = sprintf ( msg, "No text for (FSERR %d)", myerr ); else msg [mylen] = 0; fprintf ( stderr, "\n%s\n", msg ); if (loc) fprintf ( stderr, "[%s]\n", loc ); } return myerr; } /*----------------------------------------------------------------*/ proc int varread_file ( char *name, int swflg, int swsecs ) { int rtv, fn, cc, len, rec, typ, ctl; s16 fop, aop, rs, nr, nw, timeout; s32 eof; char *cp, buf [MAX_BUF]; char modes [20]; char datatyp [][4] = { "Bin", "AEs", "ACt", "Asc" }; rtv = -1; fn = 0; *modes = 0; /* Disable TTY echo and newline on READX */ if (( swflg & SW_DELY ) && ! swsecs ) { FSETMODE ( 0, 4 ); if ( CCE != CCODE () ) fserr_get ( 0, 0, "FSETMODE-on" ); FCONTROL ( 0, 13, &nr ); if ( CCE != CCODE () ) fserr_get ( 0, 0, "FCNTL-EOff" ); } do { /* Open file */ XFXMASKSET (7); fop = 0505; /* Cctl,Var,Asc,Old */ aop = 0300; /* Shr,Read */ if ( ! ( swflg & SW_DEST )) { aop |= 010000; /* Copy */ strcat ( modes, "c"); } else aop |= 04000; /* Nowait */ fn = FOPEN ( XFXMASK name, fop, aop ); if ( CCE != CCODE () ) { fserr_get ( fn, 0, "FOPEN" ); break; } /* Info file */ vfn = fn; memset ( buf, ' ', 28 ); buf [28] = 0; FFILEINFO ( fn, 1, buf, 2, &fop, 3, &aop, 4, &rs, 10, &eof ); FFILEINFO ( fn, 34, &nw, 35, &nr ); rs = ( rs < 0 ? -rs : rs * 2 ); if ( swflg & SW_WAIT ) { nr = 1; FCONTROL ( fn, 45, &nr ); strcat ( modes, "w" ); } if ( swflg & SW_BOTH ) strcat ( modes, "b" ); else if ( swflg & SW_DATA ) strcat ( modes, "d" ); if ( swflg & SW_TRIM ) strcat ( modes, "t" ); if ( swflg & SW_DELY ) { nr = strlen ( modes ); sprintf ( &modes [nr], "%d", swsecs ); } fprintf ( stderr, "%s fop 0%o aop 0%o rs %d eof %d R%d W%d %s\n", buf, fop, aop, rs, eof, nr, nw, modes ); if ( rs >= sizeof (buf) ) { fprintf ( stderr, "Recsize %d >= max %d\n", rs, sizeof (buf) ); break; } /* Read file */ rec = 0; do { /* Delay display */ if ( rec && ( swflg & SW_DELY )) /* Dont delay on 1st record */ { if ( swsecs > 0 ) sleep ( swsecs ); fprintf ( stderr, "\a" ); fflush ( stderr ); if ( ! swsecs ) len = READX ( buf, -1 ); } /* Timeout on no-wait */ if ( ! ( swflg & SW_WAIT )) { FFILEINFO ( fn, 34, &nw, 10, &eof ); if ( nw || 0 == eof ) { timeout = 1; FCONTROL ( fn, 4, &timeout ); } } /* Read record */ len = FREAD ( fn, buf, -rs ); cc = CCODE (); if ( CCE != cc ) { if ( CCG == cc ) rtv = 0; else { ctl = fserr_get ( fn, -1, 0 ); if ( 22 == ctl ) rtv = 0; else fserr_get ( fn, ctl, "FREAD" ); } break; } if ( aop & 04000 ) { /* IOWAIT */ ctl = IOWAIT ( fn, buf, &nr ); cc = CCODE (); len = nr; if ( CCE != cc ) { if ( CCG == cc ) rtv = 0; else { ctl = fserr_get ( fn, -1, 0 ); if ( 22 == ctl || 79 == ctl ) rtv = 0; else fserr_get ( fn, ctl, "IOWAIT" ); } break; } } /* CCTL test */ ctl = 0; cp = buf; if ( fop & 0400 ) { ctl = (unsigned char) *cp++; --len; } typ = print_chk ( cp, len ); /* Display info */ if ( ! ( swflg & SW_DATA ) || ( swflg & SW_BOTH )) { if ( fop & 0400 ) printf ( "Rec %4d %s %3u[%c] %4d", rec, datatyp [typ], ctl, ( ' ' <= ctl && ctl <= '~' ? ctl : ' ' ), len ); else printf ( "Rec %4d %s %4d", rec, datatyp [typ], len ); if ( swflg & SW_BOTH ) printf ( ":" ); else printf ( "\n" ); fflush ( stdout ); } /* Display data */ if ( swflg & SW_DATA ) { if ( ! typ ) printf ( "--Binary data %d\n", len ); else { if ( swflg & SW_TRIM ) while ( len > 0 && cp [len -1] == ' ' ) --len; PRINT ( cp, -len, ctl ); } } ++rec; } while ( ! cy ); } while (0); /* Enable TTY echo and newline for READX-STDINX */ if (( swflg & SW_DELY ) && ! swsecs ) { FSETMODE ( 0, 0 ); if ( CCE != CCODE () ) fserr_get ( 0, 0, "FSETMODE-off" ); FCONTROL ( 0, 12, &nr ); if ( CCE != CCODE () ) fserr_get ( 0, 0, "FCNTL-EOn" ); } /* Close file */ if ( fn ) FCLOSE ( fn, 0, 0 ); return rtv; } /*----------------------------------------------------------------*/ proc int main ( int ac, char *av [] ) { int x, sw_flag, sw_secs; s16 jcw; char *cp, *pg, *fp; MPE_INIT (); /* Banner */ pg = av [0]; while (( cp = strchr ( pg, '/' ))) pg = cp +1; cp = strchr ( pg, '.' ); if ( cp ) *cp = 0; fprintf ( stderr, "%s %s (Max recsize %d)\n", pg, VERSION, MAX_BUF ); /* User interrupt */ trapcy_set (); /* runtime options */ fp = 0; sw_flag = 0; sw_secs = 0; for ( x = 1; x < ac; ++x ) { cp = av [x]; if ( *cp == '-' ) { ++cp; while ( *cp ) { switch ( *cp++ ) { case 's': /* Delay in seconds between record data display; implies display */ if ( ! *cp && x+1 < ac ) cp = av [++x]; sw_secs = atoi ( cp ); while ( '0' <= *cp && *cp <= '9' ) ++cp; sw_flag |= SW_DELY; break; /* Display data + info */ case 'b': sw_flag |= SW_BOTH | SW_DATA; break; /* Extented wait on FREAD */ case 'w': sw_flag |= SW_WAIT; break; /* Destructive FREAD */ case 'r': sw_flag |= SW_DEST; break; /* Trim output */ case 't': sw_flag |= SW_TRIM; break; /* Display data */ case 'd': sw_flag |= SW_DATA; break; default: fprintf ( stderr, "!! Unknown switch: %c ignored.\n", cp [-1] ); } } continue; } if ( fp ) { fprintf ( stderr, "!! Extra parameter ignored: %s\n", cp ); continue; } fp = cp; } /* Process */ jcw = 0; do { if ( ! fp ) { jcw = 2; printf ( "Usage: %s [switches] file\n", pg ); printf ( " -r Destructive read msg file\n" ); printf ( " -d Display data\n" ); printf ( " -t Trim trailing blanks on display\n" ); printf ( " -s # Seconds to wait between records -" " 0 means wait for a keypress\n" ); printf ( " -w Wait if writers exist (requires -r)\n" ); printf ( " -b Display both info and data\n" ); printf ( " JCW 0 = success\n" ); printf ( " 1 = file read error\n" ); printf ( " 2 = parameter error\n" ); printf ( "\n" ); break; } if ( varread_file ( fp, sw_flag, sw_secs )) jcw = 1; } while (0); MPE_FINISH (); return jcw; } /*----------------------------------------------------------------*/