/* 3-10-93 * The distinction between read-only and dual-I/O modes is now handled * in software, rather than by compile. The default is read-only. At * runtime, a program call to set_init(), for new set output, or to * set_reinit(), for copy sets, will flag the dual I/0 mode. * * Compile must still reflect the cpu type: * cc -c -Dcpuformat getset.c * where cpuformat is VAXFMT or SUNFMT. */ #include #include #include #include #include #include #include "metasets.h" #include "tennis.h" #define MAXERR 5 /* max. repeat errors */ #define TSHORT_SD 86 /* short 1! length */ #define TAPE 1 /* device id's */ #define DISK 2 #define PIPE 4 #define istape (intype==TAPE) #define isdisk (intype==DISK) #define ispipe (intype==PIPE) static char c_ifile[NAMLEN]; /* input name/unit # */ static short reinitlist[MAXST]; /* keys for active thru-put */ static int nreinit= 0; /* next reinitlist index */ static int prompt= 1; /* request prompt */ static int iunit= -1; /* input file descriptor */ static int intype= 0; /* holds output dev. id */ static int errcount= 0; static char *iend= NULL; char *ipointer= NULL; /* inputbuff pointer */ extern int firstmetas; /* flag meta processing */ extern int nsetdscr; extern int t_request(); extern int setcount[]; extern char *opointer,*outputbuff; extern char *inputbuff,*outputbuff; extern int inputbfsiz,outputbfsiz; extern int tennis_dual,tennis_step; /* extern int mtread(),mtrew(),mtclose(); */ /* ------------------------------------------------------------------- */ /* get_set() * User routine to advance to the next input set. * Returns the value of that set's key; includes all the metasets '[[', * '0!', '0]', etc., as well as the user sets. The condition of a repeat * I/0 error returns the T_ERR flag. An unrecognizable key will effect * skipping the rest of the current buffer and doing a new read. * * Conditions for tennis_dual = 1: * If set_reinit() was called, then tennis_dual is already 1. * If set_init() was called, then nsetdscr is > 0 before getset picks up * any 0! set. We test for that condition and set tennis_dual accordingly * in startup below. * * To access data for a given key, the user should use get_game(n) to * initialize a data pointer. */ short get_set(){ static int tsetlen= 0; static int metalast= 0; static int frstgetset= 1; char *p; short key,skey; int userset,iret,iset; int i,n,otsetlen; for(;;){ ipointer += tsetlen; /* advance ipointer */ if(ipointer >= iend){ /* test for buffer end */ if(frstgetset && nsetdscr) /* nsetdscr>0 => new sets */ tennis_dual= 1; /* => dual I/O */ frstgetset= 0; tsetlen= 0; if(iunit < 0){ t_bufalloc(0); /* alloc. buffers, if new */ t_initkeymap(); /* clr maps, if need be */ if(prompt) t_request("input filename\n? ",c_ifile); else *c_ifile= '\0'; /* force T_END */ if(t_getinput() < 0) return(T_END); } iret= ts_read(); if(errcount > MAXERR) return(T_ERR); if(iret <= 0) continue; errcount= 0; ipointer= inputbuff; iend= inputbuff+iret; } p= (char*)&key; *p= *ipointer; /* pick up key chars */ *(p+1)= *(ipointer+1); userset= isalpha(*p)&&isalpha(*(p+1)); iset= t_keymap(key); /* see if entry for */ if(userset && iset>=0){ /* user set */ tsetlen= setdscr[iset].setlen; firstmetas= 0; } else /* metasets */ switch(key){ case TSET_BOM: /* [[ */ tsetlen= BOMLEN; break; case TSET_EOM: /* ]] */ tsetlen= EOMLEN; iend= NULL; break; case TSET_BOT: /* 0[ */ if(tennis_dual){ if(firstmetas){ /* 1st input ? */ t_bufalloc(0); /* insure buffers */ opointer= outputbuff; /* init ptr. */ t_begtourney(); /* output 0[ */ } /*end dual */} case TSET_B1T: case TSET_B2T: case TSET_B3T: case TSET_B4T: /* 1[ - 9[ */ case TSET_B5T: case TSET_B6T: case TSET_B7T: case TSET_B8T: case TSET_B9T: tsetlen= BOTLEN; if(tennis_dual){ t_metacopy(tsetlen); /* copy to output */ setcount[BTCNT1]++; if(key != TSET_B9T) *opointer += 1; /* n[ -> (n+1)[ */ p= opointer+4; while(p < opointer+9) /* clr any sync */ *p++ = ' '; opointer += tsetlen; tennis_step= 0; metalast= 1; /*end dual */} break; case TSET_0SD: case TSET_1SD: case TSET_2SD: case TSET_3SD: case TSET_4SD: /* 0!-9! */ case TSET_5SD: case TSET_6SD: case TSET_7SD: case TSET_8SD: case TSET_9SD: if(tennis_dual){ if(metalast != 2){ if(firstmetas){ t_obflush(); /* set up new buffer */ ts_outsetdscr(); /* output new 0!'s 1st */ } /*(before any others!!)*/ metalast= 2; } /*end dual */} if(firstmetas && key==TSET_0SD) tsetlen= t_getsetdscr(); /* now parse input 0! */ else{ sscanf(ipointer+16,"%8d",&n); /* else just get len */ tsetlen= 24+n; /* = 24+textlng */ } if(tennis_dual){ t_metacopy(tsetlen); /* copy out input set */ otsetlen= tsetlen; /* output set length */ if(firstmetas && key==TSET_0SD){ i= nsetdscr-1; /* last parsed entry */ skey= setdscr[i].setkey; n= 0; /* clear test flag */ for(i=0;i 1! */ } else if(key != TSET_9SD) *opointer += 1; /* n! -> (n+1)! */ opointer += otsetlen; /* final bump opointer */ tennis_step= 0; /*end dual */} break; case TSET_0SS: case TSET_1SS: case TSET_2SS: case TSET_3SS: /* 0$-9$ */ case TSET_4SS: case TSET_5SS: case TSET_6SS: case TSET_7SS: case TSET_8SS: case TSET_9SS: sscanf(ipointer+16,"%8d",&n); tsetlen= 24+n; /* 24+textlng */ if(tennis_dual){ if(metalast != 3){ if(firstmetas) ts_outsrcsav(); /* do new 0$'s */ metalast= 3; } t_metacopy(tsetlen); /* output old n$ */ setcount[SSCNT1]++; if(key != TSET_9SS) *opointer += 1; /* n$ -> (n+1)$ */ opointer += tsetlen; tennis_step= 0; /*end dual */} break; case TSET_EOT: case TSET_E1T: case TSET_E2T: case TSET_E3T: case TSET_E4T: /* 0] - 9] */ case TSET_E5T: case TSET_E6T: case TSET_E7T: case TSET_E8T: case TSET_E9T: tsetlen= EOTLEN; firstmetas= 0; /* make sure turned off */ if(tennis_dual){ if(metalast != 4){ t_advopointer(); /* adv. over last user set */ metalast= 4; } t_metacopy(tsetlen); /* copy to output */ setcount[ETCNT1]++; if(key != TSET_E9T) *opointer += 1; /* n] -> (n+1)] */ p= opointer+4; while(p < opointer+9) /* clr any sync */ *p++ = ' '; opointer += tsetlen; /* adv opointer */ tennis_step= 0; /*end dual */} if(key == TSET_EOT){ /* advance over EOF */ /* if(ts_read() != 0) EOF effects ts_iclose() */ /* t_err("get_set: no EOF after EOT"); */ ts_iclose(); } break; default: t_keyerr("getset: unknown key",p); iend= NULL; /* go to next match */ break; } return(key); } } /* ------------------------------------------------------------------- */ /* get_key(ukey) * Routine to search for specified set 'ukey'. * Returns on ukey, on T_END (end of data) or on T_ERR (repeat I/O error). * This is really a cosmetic routine. Since user must still test returned * key, it can equally well be accomplished using get_set(). */ short get_key(ukey) /* get user requested key */ short ukey;{ short key; do{ key= get_set(); } while(key!=ukey && key!= T_END && key!=T_ERR); return(key); /* return for ukey, T_END, or T_ERR */ } /* ------------------------------------------------------------------- */ /* set_infile(fname): * User routine to set the name of the input file. * May be called again after receipt of T_END to reset input. * Will prevent prompting to terminal. */ set_infile(fname) char *fname;{ strcpy(c_ifile, fname); prompt= 0; /* suppress request prompt */ if(t_getinput() < 0) t_err("set_infile:\n cannot open input file"); t_bufalloc(0); /* alloc. buffers, if new */ t_initkeymap(); /* clr maps, if need be */ } /* ------------------------------------------------------------------- */ /* set_reinit(key) * Flag an input set that will remain active on the output. * Getset() tests the reinitlist[] to determine if a 0! input should * be output as a 0! or as a 1!. * Key= 1 => ALL input is to remain active (eg. for tape copies) */ set_reinit(key) short key;{ tennis_dual= 1; /* set dual I/O */ if(nreinit >= MAXST) t_err("set_reinit index >= MAXST"); reinitlist[nreinit++]= key; } /* ------------------------------------------------------------------- */ /* * This routine takes the place of set_infile when reading from * an erasable optical disk. */ set_opdisk(device,offset) char *device; int offset;{ strcpy(c_ifile,device); prompt= 0; if(t_getinput() < 0) t_err("set_opdisk:\nopen failed"); if(lseek(iunit,offset,SEEK_SET) < 0) t_err("set_opdisk:\nseek failed"); t_bufalloc(0); t_initkeymap(); } /* -------------------------------------------------------------------- */ /* copy_set(key) * User routine to copy current user set to output. * Copies full set from key on. */ copy_set(key) short key;{ char *p; char *in,*out,*dest; short ikey; int iset,count; /* advance opointer and */ if((dest= put_set(key)) == NULL) /* test for user set */ t_err("copy_set: not valid user set\n"); in= ipointer; p= (char*)&ikey; /* compare keys */ *p= *in; *(p+1)= *(in+1); if(key != ikey) t_err("copy_set: copy keys do not agree\n"); iset= t_keymap(key); count= setdscr[iset].setlen; out= opointer; while(count-- > 0) /* do copy */ *out++ = *in++; /* out <- in, thank you */ } /* ------------------------------------------------------------------- */ /* t_advopointer() * Routine from putset code to advance opointer over previous set to * current position for new set. Needed for metacopy application. */ t_advopointer(){ char *p; short okey; int iset; p= (char*)&okey; *p= *opointer; /* pick up key chars */ *(p+1)= *(opointer+1); iset= t_keymap(okey); /* advance opointer to */ if(iset >= 0) /* start of next set */ opointer += setdscr[iset].setlen; /* user set */ else{ t_keyerr("getset: no setlen, key",p); exit(1); } } /* ------------------------------------------------------------------- */ /* t_metacopy() * Routine to copy metasets from input to output buffer. * len= total size of set, ipointer-> start of set. */ t_metacopy(len) int len;{ char *lookahead; char *pin,*pout; lookahead= opointer+len; if(lookahead > outputbuff+outputbfsiz-EOMLEN) t_obflush(); pin= ipointer; pout= opointer; while(len--) *pout++ = *pin++; } /* ------------------------------------------------------------------- */ /* t_shortcopy() * Make a short 1! descriptor set, with setkey only. This is * history record for input set that remains active on output. */ /* short 1! set, TSHORT_SD bytes; need to fill in key (xx) */ static char set1SD[TSHORT_SD+2]= "\ 1! ]$[B 1 1 62\n\ BEGIN_GROUP = setdscr;\n\ setkey = xx;\n\ END_GROUP = setdscr; \n"; t_shortcopy(key) short key;{ if(opointer+TSHORT_SD > outputbuff+outputbfsiz-EOMLEN) /* lookahead */ t_obflush(); strncpy(opointer,set1SD,TSHORT_SD); /* set data */ strncpy(opointer+60,&key,2); /* xx offset 60 */ } /* --------------------------------------------------------------------- */ /* t_getsetdscr() * Routine to run parser on 0! set data. Setparse will extract the * required parameters and make a new entry in the setdscr[] array. * Returns the length of the 0! set. */ int t_getsetdscr(){ /* 12, 24 offsets hardwired in here ... */ int nset,ncpf,textlng; if(nsetdscr >= MAXST) t_err("getsetdscr: nsetdscr >= MAXST"); nset= nsetdscr++; sscanf(ipointer+12,"%4d",&ncpf); if(ncpf != 1) /* tmp. restriction on large 0! */ t_err("getsetdscr: 0! too big\n"); if(t_setparse(ipointer+24,nset) == T_ERR) /* get setdscr info */ t_err("getsetdscr: 0! parse error\n"); sscanf(ipointer+16,"%8d",&textlng); return(textlng+24); /* return set 0! size */ } /* ------------------------------------------------------------------- */ /* t_getinput() * Internal routine used to open input file and set type. * tapes start with a digit, files with an alpha. */ int t_getinput(){ if(*c_ifile==NULL || atoi(c_ifile)<0) return(-1); intype= isdigit(c_ifile[0])? TAPE: DISK; switch(intype){ case TAPE: iunit= atoi(c_ifile); break; case DISK: iunit= open(c_ifile,0); break; } if(iunit < 0) /* open must have failed */ fprintf(stderr,"getset: cannot open %s\n", c_ifile); return(0); } /* ------------------------------------------------------------- */ /* ts_read() * Reads in new buffer of set data. Calls iclose() on EOF. * Returns # of bytes read, or error condition. */ int ts_read(){ int iret; if(istape){ /* iret= mtread(iunit,inputbuff,inputbfsz); */ } else iret= read(iunit,inputbuff,inputbfsiz); if(iret == 0) /* EOF ? */ ts_iclose(); else if(iret == -1){ fprintf(stderr,"getset: read error\n"); errcount++; } return(iret); } /* ------------------------------------------------------------- */ /* ts_iclose() * Closes input unit. Resets 'iunit' and 'iend' to effect a request * for a new input. */ ts_iclose(){ if(istape){ /* mtrew(iunit); */ /* mtclose(iunit); */ } else close(iunit); iunit= -1; iend= NULL; } /* ------------------------------------------------------------- */