[alt.sources] ecu - SCO XENIX V/{2,3}86 Extended CU part 14/47

wht@tridom.uucp (Warren Tucker) (10/09/89)

---- Cut Here and unpack ----
#!/bin/sh
# this is part 14 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file fcrc.c continued
#
CurArch=14
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
     exit 1; fi
( read Scheck
  if test "$Scheck" != $CurArch
  then echo "Please unpack part $Scheck next!"
       exit 1;
  else exit 0; fi
) < s2_seq_.tmp || exit 1
echo "x - Continuing file fcrc.c"
sed 's/^X//' << 'SHAR_EOF' >> fcrc.c
X  two characters following the block. The first of these 2 bytes
X  must be taken from the high-order byte of the CRC, and the second
X  must be taken from the low-order byte of the CRC. This routine is NOT
X  called for a message which has been RECEIVED.
X--------------------------------------------------------------------------*/
Xunsigned short crc_finish(crc)
Xunsigned short crc;
X{
X	/* Call crc_update twice, passing it a character of hex 00 each time, to */
X	/* flush out the last 16 bits from the CRC calculation, and return the */
X	/* result as the value of this function. */
X	return(crc_update(crc_update(crc,'\0'),'\0'));
X}
X
X/*+-------------------------------------------------------------------------
X	usage()
X--------------------------------------------------------------------------*/
Xvoid
Xusage()
X{
X
X	ff(se,"fcrc %s\n",rev);
X	ff(se,"Calculate file crc & compare with crc stored in file\n");
X	ff(se,"Usage: fcrc [-a][-n][-u] <filelist>\n");
X	ff(se," -u causes update of crc if not correct\n");
X	ff(se,"    or adds CHK=0x???? record if not present\n");
X	ff(se,"    (CRC will not be updated in file with unrecognized suffix.\n");
X	ff(se," -r<fname> if -u, placed updated filenames in <fname>\n");
X	ff(se," -n do not print files whose crc does not match\n");
X	ff(se," -a include All characters in checksum (normally\n");
X	ff(se,"    CRC does not include 0x0A or 0x0D characters)\n");
X	ff(se," -m treat MSDOS assembler files correctly even\n");
X	ff(se,"    under UNIX\n");
X	ff(se,"CRC never includes trigger (first line of file).\n");
X	ff(se,"Switch placement on command line is not critical.\n");
X	exit(1);
X}	/* end of usage */
X/*+-------------------------------------------------------------------------
X    to_upper()
X  one would think that these were relatively standard
X  types of thing, but MSC/Xenix specifies toupper() to convert to upper
X  case if not already and Unix says to adjust without testing,
X  so, two stupid little routines here
X  ASCII only -- no EBCDIC gradoo here please
X--------------------------------------------------------------------------*/
Xchar to_upper(ch)
Xregister char ch;
X{ 
X	return( ((ch >= 'a') && (ch <= 'z')) ? ch - 0x20 : ch);
X}   /* end of to_upper() */
X
X/*+-------------------------------------------------------------------------
X    str_index:  Upper/Lower [case insensitive] Index functioni
X
X  Returns position of 'str2' in 'str1' if found
X  If 'str2' is null, then 0 is returned (null matches anything)
X  Returns -1 if not found
X--------------------------------------------------------------------------*/
Xint str_index(str1,str2)
Xregister char *str1;	/* the (target) string to search */
Xregister char *str2;	/* the (comparand) string to search for */
X{
X	register int istr1 = 0;				/* moving index into str1 */
X	register char *mstr = str1;			/* moving string pointer */
X	register int str2l = strlen(str2);	/* length of comparand string */
X
X	if(str2[0] == '\0')             /* null string matches anything */
X		return(0);
X	while(1)
X	{
X		if(*mstr == '\0')           /* if we exhaust target string, flunk */
X			return(-1);
X		/* Can we find either case of first comparand char in target? */
X		if(*mstr == *str2)
X		{
X			/* we have a first char match... does rest of string match? */
X			if(strncmp(mstr,str2,str2l) == 0)	/* if the rest matches, ... */
X				return(istr1);                  /* ... return match position */
X		}
X		/* we did not match this time... increment istr1, mstr and try again */
X		++istr1;
X		++mstr;
X	}
X}	/* end of str_index */
X
X/*+-------------------------------------------------------------------------
X	trigger_type(source_type,trigger_str)
X--------------------------------------------------------------------------*/
Xvoid
Xtrigger_type(source_type,trigger_str)
Xint source_type;
Xchar	*trigger_str;
X{
X	switch(source_type)
X	{
X	case STYPE_c:
X		strcpy(trigger_str,"/* CHK=0x");
X		break;
X	case STYPE_asm:
X		if((msdos) || msdos_switch)
X			strcpy(trigger_str,";  CHK=0x");
X		else
X			strcpy(trigger_str,"** CHK=0x");
X		break;
X	case STYPE_make:
X		strcpy(trigger_str,"#  CHK=0x");
X		break;
X	case STYPE_bat:
X		strcpy(trigger_str,"rem CK=0x");
X		break;
X	default:
X		strcpy(trigger_str,"$%#$");
X	}
X
X}	/* end of trigger_type */
X
X/*+-------------------------------------------------------------------------
X	filecrc(filename,crc_returned,crc_found)
X--------------------------------------------------------------------------*/
Xint
Xfilecrc(filename,crc_returned,crc_found,source_type)
Xchar *filename;
Xunsigned	*crc_returned;
Xchar *crc_found;
Xint source_type;
X{
X	register unsigned itmp;
X	register unsigned short crc;
X	register int crc_char;
X	/* register unsigned char x, y; */
X	FILE	*fin;
X	char	crc_string[128];
X	char	crc_trigger[25];
X	register char *rptr;
X	extern int errno;
X
X	trigger_type(source_type,crc_trigger);
X
X	if( (fin = fopen(filename,"r")) == NULL)
X		return(1);
X
X	setbuf(fin,NULL);
X
X	errno = -2;
X	if(fgets(crc_string,sizeof(crc_string),fin) == NULL)
X	{
X		sprintf(errmsg,"Cannot read file %s: ",filename);
X		if(errno == -2)
X			fprintf(stderr,"%s: empty file\n",errmsg);
X		else
X			perror(errmsg);
X		fclose(fin);
X		return(2);
X	}
X
X	if((itmp = str_index(crc_string,crc_trigger)) != 0)
X		strcpy(crc_found,"NONE");
X	else
X	{
X		strncpy(crc_found,&crc_string[9],4);
X		crc_found[4] = 0;
X	}
X
X	crc = crc_clear();
X
X	if(*crc_found == 'N')	/* if we did not find the target string */
X	{
X		for(itmp = 0; itmp < strlen(crc_string); itmp++)
X			crc = crc_update(crc,crc_string[itmp]);
X	}
X
X	while((itmp = read(fileno(fin),rdbuf,sizeof(rdbuf))) > 0)
X	{
X		rptr = rdbuf;
X		while(itmp--)
X		{
X			if((skip_cr_nl == 0) || ((*rptr != 0x0A) && (*rptr != 0x0D)))
X				crc = crc_update(crc,*rptr);
X			rptr++;
X		}
X	}
X	*crc_returned = crc_finish(crc);
X	fclose(fin);
X	return(0);
X
X#if SkipThis	/* algorithm for checking incoming crc'd msg */
X	x = (unsigned char)((crc & 0xff00) >> 8);
X	y = (unsigned char)(crc & 0x00ff);
X	crc = crc_clear();
X	for(ibuf=0; ibuf<buflen; ++ibuf)
X		crc = crc_update(crc,buf[ibuf]);
X	crc = crc_update(crc,x);
X	crc = crc_update(crc,y);
X	/* If the result was 0, then message was received without error */
X#endif
X
X}	/* end of filecrc() */
X
X/*+-----------------------------------------------------------------------
X	build_temp_names()
X
X  Build temp filenames for munging around
X------------------------------------------------------------------------*/
Xvoid
Xbuild_temp_names(base_fname)
Xregister char *base_fname;
X{
X	register char *cptr;
X
X#if MSDOS
X	sprintf(tempf,"$fcrctmp.tmp");
X	sprintf(savef,"$fcrcsav.sav");
X#else
X	strcpy(tempf,base_fname);
X	if((cptr = strrchr(tempf,'/')) == NULL)
X		cptr = tempf;
X	else
X		++cptr;
X	*cptr = '@';
X	strcpy(savef,base_fname);
X	if((cptr = strrchr(savef,'/')) == NULL)
X		cptr = savef;
X	else
X		++cptr;
X	*cptr = ':';
X#endif
X
X	unlink(tempf);
X	unlink(savef);
X
X}	 /* end of build_temp_names */
X
X/*+-------------------------------------------------------------------------
X	main()
X--------------------------------------------------------------------------*/
Xmain(argc,argv,envp)
Xint argc;
Xchar	**argv;
Xchar	**envp;
X{
X	register int itmp;
X	register int update_flag = 0;
X	register int no_print_ok = 0;
X	register int did_update = 0;
X	register int match = 0;
X	register int source_type;
X	register int iargv;
X	register int fdin;
X	register int fdout;
X	register char *cptr;
X	char	crc_calculated[6];
X	char	crc_found[6];
X	unsigned crc;
X	FILE	*fp_report = NULL;
X	struct stat statbuf;
X#if DEBUG
X	char s80[80];
X#endif
X
X	setbuf(stdout,NULL);
X	setbuf(stderr,NULL);
X
X	if(argc == 1)
X		usage();
X
X	for(iargv = 1; iargv < argc; iargv++)
X	{
X		if(*argv[iargv] != '-')
X			continue;
X		itmp = 1;
X		while(argv[iargv][itmp])
X		{
X			switch(argv[iargv][itmp])
X			{
X			case 'm':
X				msdos_switch = 1;
X				if(msdos)
X					ff(se,"-m switch not required under MSDOS\n");
X				break;
X			case 'u':
X				update_flag = 1;
X				break;
X			case 'n':
X				no_print_ok = 1;
X				break;
X			case 'a':		/* all chars */
X				skip_cr_nl = 0;
X				break;
X			case 'r':
X				if((fp_report = fopen(&argv[iargv][itmp+1],"a")) == NULL)
X				{
X					perror(&argv[iargv][itmp+1]);
X					exit(1);
X				}
X				goto NEXT_ARG;
X			default:
X				ff(se,"Unrecognized switch: -%c\n",
X				    argv[iargv][itmp]);
X				usage();
X			}
X			itmp++;
X		}
XNEXT_ARG:	
X		;
X	}
X
X	for(iargv = 1; iargv < argc; iargv++)
X	{
X		if(*argv[iargv] == '-')
X			continue;
X		if(stat(argv[iargv],&statbuf))
X		{
X			perror(argv[iargv]);
X			continue;
X		}
X		if((statbuf.st_mode & S_IFMT) != S_IFREG)
X		{
X			ff(se,"not regular file: %s\n",argv[iargv]);
X			continue;
X		}
X
X		source_type = -1;		/* start with bad number */
X		itmp = strlen(argv[iargv]);
X
X		cptr = strrchr(argv[iargv],'/');
X		if(cptr == NULL)
X			cptr = argv[iargv];
X		else
X			++cptr;
X
X		if((itmp >= 2) && (strcmpi(&argv[iargv][itmp - 2],".h") == 0))
X			source_type = STYPE_c;
X		else if((itmp >= 2) && (strcmpi(&argv[iargv][itmp - 2],".c") == 0))
X			source_type = STYPE_c;
X		else if((itmp >= 2) && (strcmpi(&argv[iargv][itmp - 2],".y") == 0))
X			source_type = STYPE_c;
X		else if((itmp >= 2) && (strcmpi(&argv[iargv][itmp - 2],".l") == 0))
X			source_type = STYPE_c;
X		else if((itmp >= 4) && (strcmpi(&argv[iargv][itmp - 4],".asm") == 0))
X			source_type = STYPE_asm;
X		else if((itmp >= 4) && (strcmpi(&argv[iargv][itmp - 4],".68k") == 0))
X			source_type = STYPE_asm;
X		else if((itmp >= 4) && (strcmpi(&argv[iargv][itmp - 3],".sa") == 0))
X			source_type = STYPE_asm;
X		else if((itmp >= 3) && (strcmpi(&argv[iargv][itmp - 3],".eq") == 0))
X			source_type = STYPE_asm;
X		else if((itmp >= 2) && (strcmpi(&argv[iargv][itmp - 2],".s") == 0))
X			source_type = STYPE_asm;
X#ifdef MSDOS
X		else if((itmp >= 4) && (strcmpi(&argv[iargv][itmp - 4],".MAK") == 0))
X			source_type = STYPE_make;
X#endif
X		else if((itmp >= 5) && (strcmpi(&argv[iargv][itmp - 5],".make") == 0))
X			source_type = STYPE_make;
X		else if((itmp >= 3) && (strcmpi(&argv[iargv][itmp - 3],".ep") == 0))
X			source_type = STYPE_make;
X		else if((itmp >= 3) && (strcmpi(&argv[iargv][itmp - 3],".mi") == 0))
X			source_type = STYPE_make;
X		else if((itmp >=  5) && (strncmpi(cptr,"Make",4) == 0))
X			source_type = STYPE_make;
X#ifndef MSDOS
X		else if((itmp >=  5) && (strncmpi(cptr,"make",4) == 0))
X			source_type = STYPE_make;
X#endif
X#ifdef MSDOS
X		else if((itmp >= 4) && (strcmpi(&argv[iargv][itmp - 4],".bat") == 0))
X			source_type = STYPE_bat;
X#endif
X
X		if(itmp = filecrc(argv[iargv],&crc,crc_found,source_type))
X		{
X			switch(itmp)
X			{
X			case 1:
X				sprintf(errmsg,"Cannot access file %s: ",argv[iargv]);
X				perror(errmsg);
X			default:
X				break;
X			}
X		}
X		else
X		{
X			sprintf(crc_calculated,"%04x",crc);
X			for(crc = 0; crc < strlen(crc_calculated); crc++)
X				crc_calculated[crc] = to_upper(crc_calculated[crc]);
X			if(source_type < 0)
X			{
X				printf("%s %s %s --> unknown file type\n",crc_found,
X				    crc_calculated,argv[iargv]);
X				continue;
X			}
X			if(update_flag)
X			{
X				did_update = 0;
X				if(crc_found[0] == 'N')
X				{
X					if(access(argv[iargv],2))
X					{
X						printf("%s %s %s --> update write access denied\n",
X							crc_found,crc_calculated,argv[iargv]);
X						continue;
X					}
X					build_temp_names(argv[iargv]);	/* global 'tempf'/'savef' */
X
X					if((fdout = open(tempf,O_CREAT | O_WRONLY,0644)) < 0)
X					{
X						ff(se,"trigger add cannot open tempf...abort!\n");
X						perror(tempf);
X						exit(210);
X					}
X					trigger_type(source_type,trigger);
X					if(write(fdout,trigger,strlen(trigger)) < 0)
X					{
X						ff(se,"trigger add temp file write error\n");
X						perror(tempf);
X						exit(211);
X					}
X					if(write(fdout,"....",4) < 0)
X					{
X						ff(se,"trigger add temp file write error\n");
X						perror(tempf);
X						exit(211);
X					}
X					if(source_type == STYPE_c)
X						if(write(fdout," */",3) < 0)
X						{
X							ff(se,"trigger add temp file write error\n");
X							perror(tempf);
X							exit(213);
X						}
X					if(write(fdout,"\n",1) < 0)
X					{
X						ff(se,"trigger add temp file write error\n");
X						perror(tempf);
X						exit(215);
X					}
X					if((fdin = open(argv[iargv],O_RDONLY,0)) < 0)
X					{
X						ff(se,"Logic error: open for trigger add failed\n");
X						perror(argv[iargv]);
X						exit(200);
X					}
X					while((buflen = read(fdin,rdbuf,sizeof(rdbuf))) > 0)
X					{
X#if DEBUG
X						printf("new file read count %d\n",buflen);
X#endif
X						if(write(fdout,rdbuf,buflen) < 0)
X						{
X							ff(se,"trigger add fwrite failure..abort!\n");
X							perror(tempf);
X							exit(201);
X						}
X					}
X#if DEBUG
X					printf("new file read count exit %d\n",buflen);
X#endif
X					if(buflen < 0)
X					{
X						ff(se,"read error: trigger add\n");
X						perror(argv[iargv]);
X						exit(200);
X					}
X					close(fdin);
X					close(fdout);
X#if MSDOS
X					/* MSC 3.0 rename(to,from) */
X					/* MSC 4.0 rename(from,to) */
X					/* MSC 5.0 rename(from,to) (not verified, but logical) */
X					if(rename(argv[iargv],savef))	/* MSC 4.0 */
X					{
X						ff(se,"trigger add rename %s to %s failed\n",
X						    argv[iargv],savef);
X						perror("rename");
X						exit(202);
X					}
X					if(rename(tempf,argv[iargv]))	/* MSC 4.0 */
X					{
X						ff(se,"trigger add rename 2 %s to %s failed\n",
X						    tempf,argv[iargv]);
X						perror("rename");
X						ff(se,"SORRY, BUT SEE THIS: YOUR FILE IS NOW IN %s\n",
X						    savef);
X						exit(202);
X					}
X					if(unlink(savef))
X					{
X						char	pmsg[80];
X						sprintf(pmsg,"trigger add unlink of %s failed",savef);
X						perror(pmsg);
X						exit(202);
X					}
X#endif
X
X#if SYSV
X					if(link(argv[iargv],savef))
X					{
X						ff(se,"ln %s to %s failed\n",argv[iargv],savef);
X						perror("trigger add link 1 failure");
X						exit(202);
X					}
X#if DEBUG
X					printf("link1:\n");
X					sprintf(s80,"fstat %s %s",argv[iargv],savef);
X					system(s80);
X#endif
X					if(unlink(argv[iargv]))
X					{
X						ff(se,"unlink %s failed\n",argv[iargv]);
X						perror("trigger add unlink 1 failure");
X						ff(se,"SORRY, BUT SEE THIS: YOUR FILE IS NOW IN %s\n",
X						    savef);
X						exit(202);
X					}
X#if DEBUG
X					printf("unlink %s ok\n",argv[iargv]);
X#endif
X					if(link(tempf,argv[iargv]))
X					{
X						ff(se,"ln %s to %s failed\n",tempf,argv[iargv]);
X						perror("trigger add link 2 failure");
X						exit(202);
X					}
X#if DEBUG
X					printf("link2:\n");
X					sprintf(s80,"fstat %s %s",tempf,argv[iargv]);
X					system(s80);
X#endif
X					if(unlink(savef))	/* ok to delete old file now */
X					{
X						char	pmsg[80];
X						sprintf(pmsg,"trigger add unlink of %s failure",savef);
X						perror(pmsg);
X						exit(202);
X					}
X#if DEBUG
X					printf("unlink %s ok\n",savef);
X#endif
X					if(unlink(tempf))	/* and temp link to new file */
X					{
X						char	pmsg[80];
X						sprintf(pmsg,"trigger add unlink of %s failure",savef);
X						perror(pmsg);
X						exit(202);
X					}
X#if DEBUG
X					printf("unlink %s ok\n",tempf);
X#endif
X#endif
X
X#if defined(pyr)
X					if(rename(argv[iargv],savef))	/* rename(from,to) */
X					{
X						ff(se,"trigger add rename 1 failure.abort!\n");
X						exit(202);
X					}
X					if(rename(tempf,argv[iargv]))
X					{
X						ff(se,"trigger add rename 2 failure...abort!\n");
X						ff(se,"SORRY, BUT SEE THIS: YOUR FILE IS NOW IN %s\n",
X						    savef);
X						exit(202);
X					}
X					if(unlink(savef))
X					{
X						char	pmsg[80];
X						sprintf(pmsg,"trigger add unlink of %s failure",savef);
X						perror(pmsg);
X						exit(202);
X					}
X#endif
X					if(itmp = filecrc(argv[iargv],&crc,crc_found,source_type))
X					{
X						ff(se,"2nd crc after trigger add failed\n");
X						exit(220);
X					}
X					sprintf(crc_calculated,"%04x",crc);
X					for(crc = 0; crc < strlen(crc_calculated); crc++)
X						crc_calculated[crc] = to_upper(crc_calculated[crc]);
X					strcpy(crc_found,".NEW");
X				}	/* end of found no crc tag in file */
X
X				if(strcmp(crc_found,crc_calculated) != 0)
X				{
X					if(access(argv[iargv],2))
X					{
X						printf("%s %s %s --> update write access denied\n",
X							crc_found,crc_calculated,argv[iargv]);
X						continue;
X					}
X					if((itmp = open(argv[iargv],O_RDWR,0755)) < 0)
X					{
X						sprintf(errmsg,"Cannot open for update write: %s: ",
X						    argv[iargv]);
X						perror(errmsg);
X					}
X					else
X					{
X#ifndef L_SET
X						if(lseek(itmp,9L,0) < 0)
X#else
X							if(lseek(itmp,9L,L_SET) < 0)
X#endif
X							{
X								sprintf(errmsg,"Cannot seek for update write: %s: ",
X								    argv[iargv]);
X								perror(errmsg);
X								close(itmp);
X							}
X							else
X							{
X								if(write(itmp,crc_calculated,4) < 0)
X								{
X/* code folded from here */
X	sprintf(errmsg,"Cannot write updated crc to %s",
X	    argv[iargv]);
X	perror(errmsg);
X	exit(1);
X/* unfolding */
X								}
X								close(itmp);
X								did_update = 1;
X								printf("%s %s %s --> updated\n",crc_found,
X								    crc_calculated,argv[iargv]);
X								if(fp_report)
X/* code folded from here */
X	fprintf(fp_report,"%s\n",argv[iargv]);
X/* unfolding */
X								continue;
X							}	/* end of actually updating file */
X					}		/* end of we could open for updating */
X				}			/* end of file needed updating */
X			}				/* end of if update_flag */
X
X			match = (strcmp(crc_calculated,crc_found) == 0);
X			if((match && (no_print_ok == 0)) || !match)
X				printf("%s %s %s",crc_found,crc_calculated,argv[iargv]);
X			if(!match)
X				printf(" --> file crc not current");
X			if((match && (no_print_ok == 0)) || !match)
X				printf("\n");
X		}
X	}
X
X	if(fp_report)
X		fclose(fp_report);
X	exit(0);
X
X}	/* end of main() */
X/* end of fcrc.c */
X
X/* vi: set tabstop=4 shiftwidth=4: */
SHAR_EOF
echo "File fcrc.c is complete"
chmod 0644 fcrc.c || echo "restore of fcrc.c fails"
echo "x - extracting feval.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > feval.c &&
X/* CHK=0xFBCE */
X/*+-------------------------------------------------------------------------
X    feval.c
X	Copyright 1989 Warren H. Tucker, III.  All rights reserved.
X
X    feval_int(param,&int_returned)
X    feval_str(param,&esd_to_be_plugged)
X
X  These routines are called with param.index as follows:
X
X         !nnnnn       nnn is name of function
X          ^
X          |
X
X  Defined functions:
X	feval_int(param,value)
X	feval_str(param,result_esd)
X	strfunc_left(param,scratch_esd,result_esd)
X	strfunc_right(param,scratch_esd,result_esd)
X
X--------------------------------------------------------------------------*/
X/*+:EDITS:*/
X/*:07-03-1989-22:57-wht------------- ecu 2.00 ---------------- */
X/*:06-24-1989-16:53-wht-flush edits --- ecu 1.95 */
X
X#include "ecu.h"
X#include "ecuerror.h"
X#include "esd.h"
X#include "proc.h"
X#include "var.h"
X
X#define FIinstr		1
X#define FIlen		2
X#define FIstoi		3
X#define FIctoi		4
X#define FIbaud		5
X#define FIconn		6
X#define FIcsec		7
X#define FIpid		8
X#define FIrchr		9
X#define FIrchrc		10
X#define FIxchr		11
X#define FIxchrc		12
X#define FIlgetc		13
X#define FIargc		14
X#define FIftell		15
X#define FIfmode		16
X#define FIisdir		17
X#define FIisreg		18
X#define FIischr		19
X#define FIfatime	20
X#define FIfmtime	21
X#define FIfsize		22
X#define FIcolors	23
X#define FImatch		24
X
X
XKEYTAB feval_int_tbl[] =
X{
X	{"argc",FIargc},
X	{"baud",FIbaud},
X	{"colors",FIcolors},
X	{"conn",FIconn},
X	{"csec",FIcsec},
X	{"ctoi",FIctoi},
X	{"fatime",FIfatime},
X	{"fmode",FIfmode},
X	{"fmtime",FIfmtime},
X	{"fsize",FIfsize},
X	{"ftell",FIftell},
X	{"instr",FIinstr},
X	{"ischr",FIischr},
X	{"isdir",FIisdir},
X	{"isreg",FIisreg},
X	{"len",FIlen},
X	{"lgetc",FIlgetc},
X	{"match",FImatch},
X	{"pid",FIpid},
X	{"rchr",FIrchr},
X	{"rchrc",FIrchrc},
X	{"stoi",FIstoi},
X	{"xchr",FIxchr},
X	{"xchrc",FIxchrc},
X	{(char *)0,0}
X};
X
X#define FSleft		2
X#define FSright		3
X#define FSmid		4
X#define FSdate		5
X#define FSmonth		6
X#define FSday		7
X#define FScgets		9
X#define FScgetc		10
X#define FSitos		11
X#define FSchr		12
X#define FSdir		13
X#define FStty		14
X#define FSrdesc		15
X#define FSrname		16
X#define FSline		17
X#define FSrtel		18
X#define FSargv		19
X#define FStime		20
X#define FStimes		21
X#define FSedate		22
X#define FSetime		23
X#define FSenvvar	24
X#define FSlogname	25
X#define FSfmodestr	26
X#define FSerrstr	27
X
X
XKEYTAB feval_str_tbl[] =
X{
X	{"argv",FSargv},
X	{"cgetc",FScgetc},
X	{"cgets",FScgets},
X	{"chr",FSchr},
X	{"date",FSdate},
X	{"day",FSday},
X	{"dir",FSdir},
X	{"edate",FSedate},
X	{"etime",FSetime},
X	{"errstr",FSerrstr},
X	{"fmodestr",FSfmodestr},
X	{"envvar",FSenvvar},
X	{"logname",FSlogname},
X	{"itos",FSitos},
X	{"left",FSleft},
X	{"line",FSline},
X	{"mid",FSmid},
X	{"month",FSmonth},
X	{"rdesc",FSrdesc},
X	{"right",FSright},
X	{"rname",FSrname},
X	{"rtelno",FSrtel},
X	{"time",FStime},
X	{"times",FStimes},
X	{"tty",FStty},
X	{(char *)0,0}
X};
X
Xextern char curr_dir[];
Xextern long xmit_chars;
Xextern long xmit_chars_this_connect;
Xextern int proctrace;
Xextern PCB *pcb_stack[];
Xextern int proc_level;
Xextern char *sys_errlist[];
Xextern int sys_nerr;
X
Xchar *day_of_week_list = "SunMonTueWedThuFriSat";
Xchar *month_name_list = "JanFebMarAprMayJunJulAugSepOctNovDec";
X
X/*+-------------------------------------------------------------------------
X    erc = feval_int(param,&int_returned);
XFunctions (parameter types are expressed by the usage of variables)
X--------------------------------------------------------------------------*/
Xfeval_int(param,value)
XESD *param;
Xlong *value;
X{
Xregister erc;
Xregister keyword_token;
Xint index_save;
XESD *tesd1 = (ESD *)0;
XESD *tesd2 = (ESD *)0;
Xulong int1,int2,int3;
Xchar s32[32];
X
X	index_save = param->index;
X
X	if(erc = get_alphanum_zstr(param,s32,sizeof(s32)))
X	{
X		erc = eInvalidFunction;
X		goto RETURN;
X	}
X
X	keyword_token = keyword_lookup(feval_int_tbl,s32);
X	switch(keyword_token)
X	{
X/* LEN($S0)         length of $S0 */
X	case FIlen:
X		if(!(tesd1 = make_esd(256)))
X		{
X			erc = eNoMemory;
X			goto RETURN;
X		}
X		if(erc = skip_paren(param,1))
X			goto RETURN;
X		if(erc = gstr(param,tesd1))
X			goto RETURN;
X		if(erc = skip_paren(param,0))
X			goto RETURN;
X		*value = (long)tesd1->cb;
X		break;
X
X/* INSTR($I0,$I1)   index of first occurrence of $I1 in $I0, -1 if none */
X	case FIinstr:
X		if(!(tesd1 = make_esd(256)))
X		{
X			erc = eNoMemory;
X			goto RETURN;
X		}
X		if(!(tesd2 = make_esd(256)))
X		{
X			erc = eNoMemory;
X			goto RETURN;
X		}
X		if(erc = skip_paren(param,1))
X			goto RETURN;
X		if(erc = gstr(param,tesd1))
X			goto RETURN;
X		if(erc = skip_comma(param))
X			goto RETURN;
X		if(erc = gstr(param,tesd2))
X			goto RETURN;
X		if(erc = skip_paren(param,0))
X			goto RETURN;
X
X		*value = (long)ulindex(tesd1->pb,tesd2->pb);
X		break;
X
X	case FImatch:
X		if(!(tesd1 = make_esd(256)))
X		{
X			erc = eNoMemory;
X			goto RETURN;
X		}
X		if(!(tesd2 = make_esd(256)))
X		{
X			erc = eNoMemory;
X			goto RETURN;
X		}
X		if(erc = skip_paren(param,1))
X			goto RETURN;
X		if(erc = gstr(param,tesd1))
X			goto RETURN;
X		if(erc = skip_comma(param))
X			goto RETURN;
X		if(erc = gstr(param,tesd2))
X			goto RETURN;
X		if(erc = skip_paren(param,0))
X			goto RETURN;
X
X		erc = regexp_operation(tesd1->pb,tesd2->pb,value);
X		break;
X
X	case FIargc:
X		if(!proc_level)
X		{
X			pputs("not executing procedure\n");
X			erc = eFATAL_ALREADY;
X			break;
X		}
X		*value = (long)pcb_stack[proc_level - 1]->argc;
X		break;
X
X	case FIcolors:
X		if(erc = ifunc_colors(value))
X			goto RETURN;
X		break;
X
X	case FIftell:
X		if(erc = ifunc_ftell(param,value))
X			goto RETURN;
X		break;
X
X	case FIfmode:
X		if(erc = ifunc_fmode(param,value))
X			goto RETURN;
X		break;
X
X	case FIfsize:
X		if(erc = ifunc_fsize(param,value))
X			goto RETURN;
X		break;
X
X	case FIfmtime:
X		if(erc = ifunc_fmtime(param,value))
X			goto RETURN;
X		break;
X
X	case FIfatime:
X		if(erc = ifunc_fatime(param,value))
X			goto RETURN;
X		break;
X
X	case FIischr:
X		if(erc = ifunc_ischr(param,value))
X			goto RETURN;
X		break;
X
X	case FIisdir:
X		if(erc = ifunc_isdir(param,value))
X			goto RETURN;
X		break;
X
X	case FIisreg:
X		if(erc = ifunc_isreg(param,value))
X			goto RETURN;
X		break;
X
X	case FIbaud:
X		*value = (long)Lbaud;
X		erc = 0;
X		break;
X
X	case FIpid:
X		*value = (long)getpid();
X		erc = 0;
X		break;
X
X	case FIcsec:
X		*value = (Lmodem_off_hook) ? Loff_hook_time : -1;
X		erc = 0;
X		break;
X
X	case FIconn:
X		*value = (long)(Lmodem_off_hook) ? 1 : 0;
X		erc = 0;
X		break;
X
X	case FIxchr:
X		*value = xmit_chars;
X		erc = 0;
X		break;
X
X	case FIxchrc:
X		*value = xmit_chars_this_connect;
X		erc = 0;
X		break;
X
X	case FIrchr:
X		shmx_rc_report(value,&int1);
X		break;
X
X	case FIrchrc:
X		shmx_rc_report(&int1,value);
X		erc = 0;
X		break;
X
X/* LGETC($I0) get char from line, waiting for $I0 msec
Xreturns  character read or -1 if none read in time */
X	case FIlgetc:
X		if(erc = skip_paren(param,1))
X			goto RETURN;
X		if(erc = gint(param,&int1))
X			goto RETURN;
X		if(erc = skip_paren(param,0))
X			goto RETURN;
X		*value = (long)lgetc_timeout(int1);
X		break;
X
X	case FIctoi:
X		if(!(tesd1 = make_esd(256)))
X		{
X			erc = eNoMemory;
X			goto RETURN;
X		}
X		if(erc = skip_paren(param,1))
X			goto RETURN;
X		if(erc = gstr(param,tesd1))
X			goto RETURN;
X		if(erc = skip_paren(param,0))
X			goto RETURN;
X		if(tesd1->cb == 0)
X			*value = -1;
X		else
X			*value = (long)((unsigned)0xFF & (unsigned)tesd1->pb[0]);
X		break;
X
X	case FIstoi:
X		if(!(tesd1 = make_esd(256)))
X		{
X			erc = eNoMemory;
X			goto RETURN;
X		}
X		if(erc = skip_paren(param,1))
X			goto RETURN;
X		if(erc = gstr(param,tesd1))
X			goto RETURN;
X		if(erc = skip_paren(param,0))
X			goto RETURN;
X
X		tesd1->index = 0;
X		skip_cmd_break(tesd1);
X		*value = atol(tesd1->pb + tesd1->index);
X		break;
X
X	default:
X		erc = eInvalidFunction;
X	}   /* end of keyword lookup erc switch statement */
X
XRETURN:
X	if(tesd1)
X		free_esd(tesd1);
X	if(tesd2)
X		free_esd(tesd2);
X	return(erc);
X
X}   /* end of feval_int() */
X
X/*+------------------------------------------------------------------
X    strfunc_left(param,&scratch_esd,&result_esd)
X-------------------------------------------------------------------*/
Xint
Xstrfunc_left(param,scratch_esd,result_esd)
XESD *param;
XESD *scratch_esd;
XESD *result_esd;
X{
Xregister erc;
Xint itmp;
Xlong ltmp;
X
X	if(erc = skip_paren(param,1))
X		return(erc);
X	if(erc = gstr(param,scratch_esd))
X		return(erc);
X	if(erc = skip_comma(param))
X		return(erc);
X	if(erc = gint(param,&ltmp))
X		return(erc);
X	itmp = (int)ltmp;
X	if(itmp < 0)
X		return(eBadParameter);
X	if(erc = skip_paren(param,0))
X		return(erc);
X	/* take min of param and .cb */
X	itmp = (itmp < scratch_esd->cb) ? itmp : scratch_esd->cb;
X	if(itmp > (result_esd->maxcb - result_esd->cb) )
X		return(eBufferTooSmall);
X	memcpy(&result_esd->pb[result_esd->cb],
X	    scratch_esd->pb,itmp);
X	result_esd->cb += itmp;
X	return(erc);
X}   /* end of strfunc_left() */
X
X/*+-------------------------------------------------------------------------
X    erc = strfunc_right(param,&scratch_esd,&result_esd)
X--------------------------------------------------------------------------*/
Xint
Xstrfunc_right(param,scratch_esd,result_esd)
XESD *param;
XESD *scratch_esd;
XESD *result_esd;
X{
Xregister erc;
Xint itmp;
Xlong ltmp;
X
X	if(erc = skip_paren(param,1))
X		return(erc);
X	if(erc = gstr(param,result_esd))
X		return(erc);
X	if(erc = skip_comma(param))
X		return(erc);
X	if(erc = gint(param,&ltmp))
X		return(erc);
X	itmp = (int)ltmp;
X	if(itmp < 0)
X		return(eBadParameter);
X	if(erc = skip_paren(param,0))
X		return(erc);
X
X/* take min of param and .cb */
X	itmp = (itmp < scratch_esd->cb) ? itmp : scratch_esd->cb;
X	if(itmp > (result_esd->maxcb - result_esd->cb) )
X		return(eBufferTooSmall);
X	memcpy(&result_esd->pb[result_esd->cb],
X	    &scratch_esd->pb[scratch_esd->cb - itmp],itmp);
X	result_esd->cb += itmp;
X
X}   /* end of strfunc_right() */
X
X/*+-------------------------------------------------------------------------
X    erc = feval_str(param,&esd_to_be_plugged);
X    results are APPENDED to 'result_esd'
X--------------------------------------------------------------------------*/
Xfeval_str(param,result_esd)
XESD *param;
XESD *result_esd;
X{
Xregister erc;
Xregister itmp;
Xint index_save;
Xint int1,int2;
Xchar s32[32];
Xchar *cptr;
Xlong ltmp;
XESD *tesd1;
Xchar *get_ttyname();
Xchar *getenv();
Xchar *getlogin();
Xchar *get_elapsed_time();
Xchar *mode_map();
X
X	if(!(tesd1 = make_esd(128)))
X		return(eNoMemory);
X
X	index_save=param->index;
X
X	if(erc = get_alphanum_zstr(param,s32,sizeof(s32)-1))
SHAR_EOF
echo "End of part 14"
echo "File feval.c is continued in part 15"
echo "15" > s2_seq_.tmp
exit 0
-- 
-------------------------------------------------------------------
Warren Tucker, Tridom Corporation       ...!gatech!emory!tridom!wht 
Ker-au'-lo-phon.  An 8-foot partial flue-stop, having metal pipes
surmounted by adjustable rings, and with a hole bored near the top
of each pipe, producing a soft and "reedy" tone.