From:	CSBVAX::MRGATE!RELAY-INFO-VAX@CRVAX.SRI.COM@SMTP  3-SEP-1988 09:30
To:	ARISIA::EVERHART
Subj:	ATREAD.2_of_4


Received: From KL.SRI.COM by CRVAX.SRI.COM with TCP; Fri,  2 SEP 88 19:40:51 PDT
Received: from ucbvax.Berkeley.EDU by KL.SRI.COM with TCP; Fri, 2 Sep 88 19:23:05 PDT
Received: by ucbvax.Berkeley.EDU (5.59/1.31)
	id AA16654; Fri, 2 Sep 88 16:51:26 PDT
Received: from USENET by ucbvax.Berkeley.EDU with netnews
	for info-vax@kl.sri.com (info-vax@kl.sri.com)
	(contact usenet@ucbvax.Berkeley.EDU if you have questions)
Date: 29 Aug 88 03:23:37 GMT
From: naucse!jdc@arizona.edu  (John Campbell)
Organization: Northern Arizona University, Flagstaff, AZ
Subject: ATREAD.2_of_4
Message-Id: <849@naucse.UUCP>
Sender: info-vax-request@kl.sri.com
To: info-vax@kl.sri.com


+-+-+-+ Beginning of part 2 +-+-+-+
X      0x79, 0x7A, 0x00, 0x00, 0x00, 0x5B, 0x00, 0x00,
X0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X      0x00, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x00,
X0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
X      0x48, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
X      0x51, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X0x5C, 0x00, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
X      0x59, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
X      0x38, 0x39, 0x7C, 0x00, 0x00, 0x00, 0x00, 0xFF
X};
X
X#define MAX_BUF 65532
X#define MAX_NAME 132
X#define MAX_WILD_NAMES 80
Xstatic char tape[] = "USER$TAPE", in_line[MAX_BUF+2], out_line[MAX_BUF+2];
Xstatic char *yy_data=in_line, file_name[MAX_NAME], file_type='V',
X            file_opts[MAX_NAME], *wild_names[MAX_WILD_NAMES],
X            *exclude_names[MAX_WILD_NAMES];
Xstatic int byte_count, ebcdic_flag = 0, data_flag = 0, hdr3_flag,
X           no_tape = 0, fixed_length = 0,
X           verbose_flag=0, directory_flag=0, interactive_flag=0;
X           rec_count=0, file_id, active_flag, eof_flag = 0;
X
X/* field sizes (from ansitar.c) */
X#define LABID   3
X#define SERIAL  6
X#define OWNER   14
X#define FILEID  17
X#define SETID   6
X#define SECNO   4
X#define SEQNO   4
X#define GENNO   4
X#define GENVSNO 2
X#define CRDATE  6
X#define EXDATE  6
X#define BLOCKS  6
X#define SYSTEM  13
X#define BLKMAX  5
X#define RECMAX  5
X#define BYTOFFS 2
X#define DBYTES  4
X
X/* pad fields (reserved for future use) */
X#define VRES1   20
X#define VRES2   6
X#define VRES3   28
X#define HRES1   7
X#define H2RES1  35
X#define H2RES2  28
X
X/* Volume header label */
Xtypedef struct {
X        char    labid[LABID];         /* label identifier "VOL" */
X        char    labno;                /* label number */
X        char    serial[SERIAL];       /* volume serial number */
X        char    access;               /* accessibility */
X        char    res1[VRES1];          /* reserved for future use */
X        char    res2[VRES2];          /* reserved for future use */
X        char    owner[OWNER];         /* owner identifier */
X        char    res3[VRES3];          /* reserved for future use */
X        char    stdlabel;             /* standard label flag */
X        } VOL1_s;
X
X
X/* file header/eof label */
Xtypedef struct {
X        char    labid[LABID];         /* label identifier: "HDR" or "EOF" */
X        char    labno;                /* label number */
X        char    fileid[FILEID];       /* file identifier */
X        char    setid[SETID];         /* file set identifier */
X        char    secno[SECNO];         /* file section number */
X        char    seqno[SEQNO];         /* file sequence number */
X        char    genno[GENNO];         /* generation number */
X        char    genvsno[GENVSNO];     /* generation vsn number */
X        char    crdate[CRDATE];       /* creation date */
X        char    exdate[EXDATE];       /* expiration date */
X        char    access;               /* accessibility */
X        char    blocks[BLOCKS];       /* block count */
X        char    system[SYSTEM];       /* system code */
X        char    x1[7];                /* reserved */
X        } HDR1_s;
X
X/* deblocking hdr2/eof2 label */
Xtypedef struct {
X        char    labid[LABID];        /* label identifier: "HDR" or "EOF" */
X        char    labno;               /* label number "2" */
X        char    datatype;            /* type identifier "D" or "F" */
X        char    blkmax[BLKMAX];      /* maximum block size in bytes */
X        char    recmax[RECMAX];      /* maximum record size in bytes */
X        char    x1[H2RES1];          /* reserved */
X        char    bytoffs[BYTOFFS];    /* extra stuff at start of block */
X        char    x2[H2RES2];          /* reserved */
X        } HDR2_s;
X%}
X
X%token T_VOL1
X%token T_VOLn  /* Ignore (if even allowed in ansi) */
X%token T_HDR1
X%token T_HDR2
X%token T_HDR3
X%token T_HDR4
X%token T_HDRn  /* Ignored (user supplied) */
X%token T_TM
X%token T_DATA
X%token T_EOV   /* EOV1, EOV2, etc all treated equally. */
X%token T_EOF   /* As are EOF records. */
X
X%%
Xansi_tape:      vol_info files T_TM /* One tape mark already in ````files''. */
X                     {eof_flag = 1;}
X
Xvol_info:       vol1 voln
X
Xvol1:           T_VOL1 {act_vol1();}
X
Xvoln:           voln T_VOLn {act_ignore();}
X                | /* Empty */
X
Xfiles:          files file
X                | /* empty */
X
Xfile:           file_front eof_info T_TM
X                | multi_vol_file
X
Xfile_front:     header_info t_mark1 file_data t_mark2
X
Xfile_data:      file_data T_DATA {act_data();}
X                | /* empty */
X
Xt_mark1:         T_TM {data_flag = 1 - data_flag; act_open();}
X
Xt_mark2:         T_TM {data_flag = 1 - data_flag; act_close();}
X
Xmulti_vol_file: multi_vol_file file_front continue_info vol_info file
X                | /* empty */
X
Xheader_info:    hdr1
X                | hdr1 hdr2
X                | hdr1 hdr2 hdr4  /* Special for local file ext. */
X                | hdr1 hdr2 hdr3
X                | hdr1 hdr2 hdr3 hdr4 hdrn
X
Xhdr1:           T_HDR1 {act_hdr1();}
X
Xhdr2:           T_HDR2 {act_hdr2();}
X
Xhdr3:           T_HDR3 {act_hdr3();}
X
Xhdr4:           T_HDR4 {act_hdr4();}
X
Xhdrn:           hdrn T_HDRn {act_ignore();}
X                | /* Empty */
X
Xcontinue_info:  T_TM eov_info T_TM T_TM  {act_mount_tape (0, 1);}
X
Xeof_info:       eof_info eof
X                | /* Empty */
X
Xeof:            T_EOF {act_ignore();}
X
Xeov_info:       eov_info eov
X                | /* Empty */
X
Xeov:            T_EOV {act_ignore();}
X%%
X /*
X */
Xshort channel;
X
X
Xmain()
X{
X#define D_FILL(d,string) \
X   d.dsc$w_length  = strlen(string);\
X   d.dsc$b_dtype   = DSC$K_DTYPE_T;\
X   d.dsc$b_class   = DSC$K_CLASS_S;\
X   d.dsc$a_pointer = string;
X
X   int  status, count=0;
X   short retlen;
X   char param_buf[81];
X   struct dsc$descriptor_s dscr, retstr;
X
X/* Check the type of device that the tape descriptor points to. */
X   check_device ();
X
X   retstr.dsc$w_length = 80;
X   retstr.dsc$b_dtype  = DSC$K_DTYPE_T;
X   retstr.dsc$b_class  = DSC$K_CLASS_S;
X   retstr.dsc$a_pointer = param_buf;
X
X/* find out what flags are present. */
X   D_FILL (dscr, "DIRECTORY");
X   if (cli$present (&dscr) & 1)
X      directory_flag = 1;
X   D_FILL (dscr, "VERBOSE");
X   if (cli$present (&dscr) & 1)
X      verbose_flag = 1;
X   D_FILL (dscr, "DEBUG");
X   if (cli$present (&dscr) & 1)
X      yydebug = 1;
X   D_FILL (dscr, "INTERACTIVE");
X   if (cli$present (&dscr) & 1)
X      interactive_flag = 1;
X
X/* Fill in the exclude_names list. */
X   D_FILL (dscr, "EXCLUDE");
X   count = 0;
X   while (cli$get_value (&dscr, &retstr, &retlen) & 1) {
X      exclude_names[count] = malloc (retlen+1);
X      strncpy (exclude_names[count], param_buf, retlen);
X      exclude_names[count][retlen] = '\0';
X      if (++count > MAX_WILD_NAMES)
X         fprintf (stderr, "Too many in wild-card list\n"), exit(1);
X   }
X   exclude_names[count] = NULL;
X
X/* Fill in the wild-card parameter list. */
X   D_FILL (dscr, "P1");
X   count = 0;
X   while (cli$get_value (&dscr, &retstr, &retlen) & 1) {
X      wild_names[count] = malloc (retlen+1);
X      strncpy (wild_names[count], param_buf, retlen);
X      wild_names[count][retlen] = '\0';
X      if (++count > MAX_WILD_NAMES)
X         fprintf (stderr, "Too many in wild-card list\n"), exit(1);
X   }
X   wild_names[count] = NULL;
X
X   D_FILL (dscr, "MOUNT");
X   status = cli$present(&dscr);
X   act_mount_tape (status != CLI$_NEGATED && status != CLI$_LOCNEG, 1);
X
X   yyparse();
X}
X
X
Xact_close ()
X/*-
X   Action routine called when it is time to close the current disk file
X   (filled from act_data).
X-*/
X{
X   if (active_flag)
X      close (file_id);
X}
X
X
Xact_data()
X/*-
X   Routine to actually interpret the current yy_data buffer based on hdr2
X   setting ("F", "V", or "D").  Data is written to the terminal if interactive
X   and to the file opened in act_open().  If the user (in interactive mode)
X   chooses to skip then the file is closed and deleted here in act_data.
X*/
X{
X#define PAD_CHAR '^'
X   char *buf = in_line, *data = yy_data;
X   short buf_count, rec_count;
X   int i, blanks = 0, lecho = interactive_flag, lc = 0;
X
X   if (directory_flag || !active_flag)
X      return;   /* No data displayed. */
X
X   switch (file_type) {
X   case 'F':
X   /* Handle fixed length (text) records. */
X      for (i = 0; i < byte_count; i += fixed_length) {
X         rec_count = find_pad (&data[i], PAD_CHAR,
X               byte_count - i > fixed_length ? fixed_length : byte_count - i);
X         if (rec_count > 0) {
X            while (blanks > 0) {
X            /* Front part of yy_data is free for padding (if we need it). */
X               ots$move5 (0, NULL, ' ', fixed_length, yy_data);
X               lecho = ewrite (yy_data, fixed_length, ++lc, lecho);
X               --blanks;
X            }
X            lecho = ewrite (&data[i], rec_count, ++lc, lecho);
X/*            write (file_id, "\n", 1); */
X         }
X         else
X            ++blanks;
X         if (lecho == 3)
X            break;
X      }
X   break;
X   case 'V':
X   /* Handle variable length (length numerical) records. */
X      buf_count = get_num(&buf[0]);
X      for (i = 4; i < buf_count; i += rec_count) {
X         rec_count = get_num(&buf[i]);
X         lecho = ewrite (&data[i+4], rec_count-4, ++lc, lecho);
X/*          printf ("\n"); */
X         if (lecho == 3)
X            break;
X      }
X   break;
X   case 'D':
X   /* Handle variable length (length numerical) records. */
X      for (i = 0; i < byte_count; i += rec_count) {
X         if (!str_to_integer (&data[i], 4, &rec_count)) {
X            if (data[i] == PAD_CHAR)
X               break;
X            yyerror ("Bad integer in variable record");
X         }
X         if (rec_count > 4)
X            lecho = ewrite (&data[i+4], rec_count-4, ++lc, lecho);
X         else
X            lecho = ewrite ("\n", 1, ++lc, lecho);
X         if (lecho == 3)
X            break;
X      }
X   break;
X   default:
X      yyerror ("Impossible in act_data");
X   }
X
X   if (lecho == 3) {
X   /* Fiction--do our own close and delete.  Set the active_flag to 0. */
X      active_flag = 0;
X      close (file_id);
X      delete (file_name);
X   }
X}
X
X
Xact_hdr1 ()
X/*-
X   Action routine called when it is time to process a header 1 record.  Data
X   is in yy_data.  If the system type is DECFILE11A a flag is set to  allow
X   us to process HDR3 records.
X-*/
X{
X    int i, j, bc=0;
X    HDR1_s *hp=(HDR1_s *)yy_data;
X
X   if (verbose_flag || yydebug) act_ignore ();  /* Print info out. */
X
X/* See if we are going to try to figure out the HDR3 record. */
X   if (strncmp (hp->system, "DECFILE11A", 10) == 0)
X      hdr3_flag = 1;
X   else
X      hdr3_flag = 0;
X
X/* put a "trimmed" filename into file_name */
X   for (j = 0, i = 0; i < FILEID; i++) {
X      if (hp->fileid[i] == ' ')
X         ++bc;
X      else {
X         while (bc > 0) {
X            file_name[j++] = ' ';
X            --bc;
X         }
X         file_name[j++] = hp->fileid[i];
X      }
X   }
X   file_name[j] = '\0';   /* Terminate file name. */
X}
X
X
Xact_hdr2 ()
X/*-
X   Action routine called when it is time to process a header 2 record.  Data
X   is in yy_data.
X-*/
X{
X   HDR2_s *hp;
X
X   if (verbose_flag || yydebug) act_ignore ();  /* Print info out. */
X
X   hp = (HDR2_s *)yy_data;
X
X   file_type = hp->datatype;
X   sprintf (file_opts, "rat=cr,rfm=var,");
X   switch (file_type) {
X   case 'F':
X      if (!str_to_integer (hp->recmax, RECMAX, &fixed_length))
X         yyerror ("Bad ascii integer");
X   break;
X   case 'V':
X   case 'D':
X      fixed_length = 0;
X   break;
X   default:
X      yyerror ("Unknown file type");
X   }
X}
X
X
Xact_hdr3 ()
X/*-
X   Action routine called when it is time to process a header 3 record.
X   Header three records are currently processed only if the system is
X   DECFILE11A (since HDR3 records are system/implementation dependent).
X   Current support for HDR3 is a bit spotty.  EXE files, for instance,
X   will work while OBJ files will not.  As a rule, however, most text
X   files seem to work.  This whole routine is just here for fun anyway,
X   since such tapes can more easily be read with VMS COPY.
X-*/
X{
X   int rsize;
X
X   file_opts[0] = '\0';
X   if (hdr3_flag) {
X   /* Pick off the options in the rat and rfm, overload the hdr3 flag*/
X      hdr3_flag = 2;
X
X   /* determine the record attribute (guessing here). */
X      switch (yy_data[9]) {
X      case '0':
X      /* Convert value of maximum record size to decimal mrs string. */
X         rsize = (yy_data[4]-'0')*4096 + (yy_data[5]-'0')*256 +
X                 (yy_data[6]-'0')*16 + (yy_data[7]-'0');
X         sprintf (file_opts, "rat=blk,mrs=%d,", rsize);
X      break;
X      case '1':
X         strcat (file_opts, "rat=ftn,");
X      break;
X      case '2':
X         strcat (file_opts, "rat=cr,");
X      break;
X   /* default and '2' are rat=cr so ignore. */
X      }
X
X      switch (yy_data[11]) {
X      case '1':
X         strcat (file_opts, "rfm=fix,");
X      break;
X      case '2':
X         strcat (file_opts, "rfm=var,");
X      break;
X   /* Case 2 (variable) and 0 are the defaults anyway. */
X      case '3':
X         strcat (file_opts, "rfm=vfc,");
X      break;
X      case '4':
X         strcat (file_opts, "rfm=stm,");
X         hdr3_flag = 1;  /* No line feed. */
X      break;
X      case '5':
X         strcat (file_opts, "rfm=stmlf,");
X         hdr3_flag = 1;
X      break;
X      case '6':
X         strcat (file_opts, "rfm=stmcr,");
X         hdr3_flag = 1;
X      break;
X   /* default-- ignore. */
X      }
X   }
X
X   if (verbose_flag || yydebug) act_ignore ();  /* Print info out. */
X}
X
X
Xact_hdr4 ()
X/*-
X   Action routine to get the remaining part of the file name from
X   the HDR4 record.  (Assumes the HDR4 record contains more file
X   name, which may only be true on DECFILE11A).
X-*/
X{
X    int i, j, bc=0;
X
X   if (verbose_flag || yydebug) act_ignore ();  /* Print info out. */
X
X/* Only look at this record if the hdr3 flag is set (DECFILE11A system). */
X   if (!hdr3_flag) return;
X
X/* put a "trimmed" filename into file_name */
X   for (j = strlen(file_name), i = 5; i < 79-17+5; i++) {
X      if (yy_data[i] == ' ')
X         ++bc;
X      else {
X         while (bc > 0) {
X            file_name[j++] = ' ';
X            --bc;
X         }
X         file_name[j++] = yy_data[i];
X      }
X   }
X   file_name[j] = '\0';   /* Terminate file name. */
X}
X
X
X
Xact_ignore ()
X/*-
X   NULL action, do nothing, except we might print some information out
X   if running in debug mode.
X-*/
X{
X   int i;
X
X   if (yydebug) {
X      printf ("\n");
X      for (i=0; i < byte_count; i++) {
X         if (i != 0 && i % 76 == 0) printf ("\n -");
-+-+-+-+-+ End of part 2 +-+-+-+-+-
-- 
	John Campbell               ...!arizona!naucse!jdc

	unix?  Sure send me a dozen, all different colors.

