strings

Warren Tucker wht at tridom.uucp
Wed May 17 04:00:50 AEST 1989


This might be a little long, but maybe it'll help reduce
some further dialog (or provoke more :-|).  I have needed
nice formal string-descriptor based strings _RARELY_ and
this is a sort of tool box I pick stuff out of.  Hope it
helps.

#!/bin/sh
# shar:	Shell Archiver  (v1.22)
#
#	Run the following text with /bin/sh to create:
#	  esd2.h
#	  esd2util.c
#
sed 's/^X//' << 'SHAR_EOF' > esd2.h &&
X/* CHK=0x1793 */
X/*+-----------------------------------------------------------------------
X	esd2.h -- support header for users of esd2util.c
X	...!gatech!emory!tridom!wht
X------------------------------------------------------------------------*/
X/*+:EDITS:*/
X/*:10-31-1988-16:37-wht-esd2 adapted from esd.h/esdutil.c */
X
Xtypedef struct esd
X{
X	char	*pb;		/* full pointer to esd strings */
X	short	cb;			/* count of bytes */
X	short	maxcb;		/* maximum bytes allowed */
X	short	index;		/* next character of significance */
X	short	old_index;	/* last token (backup or error reporting) */
X}	ESD;
X
Xtypedef struct keyword_table_type	/* table terminated with null key_word */
X{
X    char    *key_word;          /* key word */
X    int     key_token;          /* token returned on match */
X} KEYTAB;
X
X/* vi: set tabstop=4 shiftwidth=4: */
SHAR_EOF
chmod 0644 esd2.h || echo "restore of esd2.h fails"
sed 's/^X//' << 'SHAR_EOF' > esd2util.c &&
X/* CHK=0x2302 */
X/*+----------------------------------------------------------------
X	esd2util.c
X	...!gatech!emory!tridom!wht
X
X  Defined functions:
X	append_zstr_to_esd(tesd,zstr)
X	esdstrindex(esd1,esd2,index1_flag,index2_flag)
X	fgetesd(tesd,fileptr)
X	fputesd(tesd,fileptr,index_flag,nl_flag)
X	free_esd(tesd)
X	get_alpha_zstr(param,strbuf,strbuf_maxcb)
X	get_alphanum_zstr(param,strbuf,strbuf_maxcb)
X	get_numeric_value(param,value)
X	get_numeric_zstr(param,strbuf,strbuf_maxcb)
X	get_word_zstr(param,strbuf,strbuf_maxcb)
X	init_esd(tesd,cptr,maxcb)
X	keyword_lookup(ktable,param)
X	make_esd(maxcb)
X	null_terminate_esd(tesd)
X	skip_cmd_break(tesd)
X	skip_cmd_char(param,skipchar)
X	skip_comma(param)
X	skip_ld_break(zstr)
X	skip_paren(param,fLeft)
X	strindex(str1,str2)
X	strip_trailing_spaces_esd(ztext)
X
X-----------------------------------------------------------------*/
X/*+:EDITS:*/
X/*:10-31-1988-16:37-wht-esd2 adapted from esd.h/esdutil.c */
X/*:04-18-1988-18:19-wht-more routines */
X/*:01-28-1987-12:30-wht-add get_word_zstr */
X/*:01-28-1987-12:00-wht-include MSC 4.0 / MSDOS compatibility */
X/*:01-16-1986-01:00-WHT-Creation of edits (version beta 1.01) */
X
X#include <stdio.h>
X#include <ctype.h>
X#include "esd2.h"
X
X#if XENIX | MSDOS
X#include <string.h>
X#else
Xextern char	*index();
X#endif
X
X/*+-------------------------------------------------------------------------
X    void null_terminate_esd(&esd)
X    puts null at 'cb' position of string (standard esd always
X    has one more byte in buffer than maxcb says)
X--------------------------------------------------------------------------*/
Xvoid
Xnull_terminate_esd(tesd)
Xregister ESD *tesd;
X{
X	tesd->pb[tesd->cb] = 0;
X}   /* end of null_terminate_esd */
X
X/*+-----------------------------------------------------------------------
X	void init_esd(tesd,cptr,maxcb)  init an esd 
X------------------------------------------------------------------------*/
Xvoid init_esd(tesd,cptr,maxcb)
Xregister ESD *tesd;
Xchar	*cptr;
Xregister int maxcb;
X{
X	tesd->pb = cptr;			/* pointer to string */
X	tesd->maxcb = maxcb;		/* max characters in buffer */
X	tesd->cb = 0;				/* current count == 0 */
X	tesd->index = 0;			/* parse index to first position */
X	tesd->old_index = 0;		/* parse index to first position */
X	*tesd->pb = 0;				/* start with null terminated string */
X
X}	/* end of init_esd */
X
X/*+-----------------------------------------------------------------------
X	esdptr = make_esd(maxcb)	allocate an esd and buffer
X------------------------------------------------------------------------*/
XESD	*
Xmake_esd(maxcb)
Xregister int maxcb;		/* desired maxcb */
X{
X	register ESD *tesd;
X	register int actual_cb;
X
X	/* we get an extra character to ensure room for null past maxcb */
X	actual_cb = maxcb + sizeof(ESD) + 1;
X	if(actual_cb & 1)		/* even allocation */
X		++actual_cb;
X	if((tesd = (ESD *)malloc( (unsigned)actual_cb )) == NULL)
X		return((ESD *)0); 	/* return NULL if failure */
X
X	init_esd(tesd,(char *)(tesd + 1),maxcb);
X	return(tesd);
X
X}	/* end of make_esd */
X
X/*+-----------------------------------------------------------------------
X	free_esd(esdptr)
X------------------------------------------------------------------------*/
Xvoid free_esd(tesd)
Xregister ESD *tesd;
X{
X	tesd->maxcb = 0;
X	tesd->cb = 0;
X	free((char *)tesd);
X}
X
X/*+----------------------------------------------------------------
X    strindex:  string index function
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
Xstrindex(str1,str2)
Xchar *str1;	/* the (target) string to search */
Xchar *str2;	/* the (comparand) string to search for */
X{
X	register int istr1 = 0;
X	register int lstr2 = strlen(str2);
X	register char *mstr = str1;	/* the (target) string to search */
X
X	if(*str2 == 0)			/* null string matches anything */
X		return(0);
X
X	while(*mstr)
X	{
X		if(*mstr == *str2)
X		{ /* we have a first char match... does rest of string match? */
X			if(!strncmp(mstr,str2,lstr2))
X				return(istr1);		/* if so, return match position */
X		}
X		mstr++;
X		istr1++;
X	}
X
X	return(-1);		/* if we exhaust target string, flunk */
X
X}   /* end of strindex */
X
X/*+-------------------------------------------------------------------------
X	esdstrindex(esd1,esd2,index1_flag,index2_flag)
X
X  Call strindex with esd1->pb and esd2->pb.
X  If index1_flag != 0, esd1->pb + esd1->index passed
X  If index2_flag != 0, esd2->pb + esd2->index passed
X--------------------------------------------------------------------------*/
Xesdstrindex(esd1,esd2,index1_flag,index2_flag)
Xregister ESD *esd1;
Xregister ESD *esd2;
Xregister int index1_flag;
Xregister int index2_flag;
X{
X	return(strindex((index1_flag) ? esd1->pb : esd1->pb + esd1->index,
X	    (index2_flag) ? esd2->pb : esd2->pb + esd2->index));
X
X}	/* end of esdstrindex */
X
X/*+----------------------------------------------------------------
X    keyword_lookup(ktable,param)
X
X  Lookup string in keyword_table struct array
X  Returns table->key_token if 'param' found in
X  'table', else -1
X
X  Beware substrings.  "type","typedef" will both match "type"
X  Ordering of table can help this.
X-----------------------------------------------------------------*/
Xkeyword_lookup(ktable,param)
Xregister KEYTAB  *ktable;
Xregister char *param;
X{
X	register int plen = strlen(param);
X
X	while(ktable->key_word)
X	{
X		if(!strncmp(ktable->key_word,param,plen))
X			return(ktable->key_token);
X		++ktable;
X	}   /* end of while */
X
X	return(-1);     /* search failed */
X
X}   /* end of keyword_lookup */
X
X/*+----------------------------------------------------------------
X    skip_cmd_break(tesd)
X
X  Finds next non-break or end of command line text
X  'tesd' is an esd with valid 'index' field
X  Returns   0		index field points to non-break character
X            -1		end of line found
X-----------------------------------------------------------------*/
Xint
Xskip_cmd_break(tesd)
Xregister ESD *tesd;
X{
X	register int cb = tesd->cb;
X	register int index = tesd->index;
X	register char *pb = tesd->pb + index;
X
X	while(index < cb)
X	{
X		if(*pb++ != 0x20)
X			break;
X		index++;
X	}
X	tesd->old_index = tesd->index = index;
X	if(index >= cb)
X		return(-1);
X	else
X		return(0);
X
X}   /* end of skip_cmd_break */
X
X/*+-------------------------------------------------------------------------
X    erc = skip_cmd_char(param,skipchar)
X--------------------------------------------------------------------------*/
Xint
Xskip_cmd_char(param,skipchar)
Xregister ESD *param;
Xregister char skipchar;
X{
X	register int erc;
X
X	if(erc = skip_cmd_break(param))
X		return(erc);
X
X	if(param->pb[param->index] == skipchar)
X	{
X		++param->index;
X		return(0);
X	}
X
X	return(-1);
X
X}   /* end of skip_cmd_char */
X
X/*+-------------------------------------------------------------------------
X    erc = skip_comma(param)
X--------------------------------------------------------------------------*/
Xint
Xskip_comma(param)
Xregister ESD *param;
X{
X	register int erc;
X
X	if(erc = skip_cmd_break(param))
X		return(erc);
X
X	if(param->pb[param->index] == ',')
X	{
X		++param->index;
X		return(0);
X	}
X
X	return(-1);
X
X}   /* end of skip_comma */
X
X/*+-------------------------------------------------------------------------
X    erc = skip_paren(fparam,LEFT or RIGHT)
X--------------------------------------------------------------------------*/
Xint
Xskip_paren(param,fLeft)
Xregister ESD *param;
Xint fLeft;          /* if =LEFT , skip left paren, else skip right */
X{
X	register int erc;
X
X	if(erc = skip_cmd_break(param))
X		return(erc);
X
X	if(fLeft)
X	{
X		if(param->pb[param->index++] == 0x28)   /* 0x28 == open parenthesis */
X			return(0);
X		else
X		{
X			--param->index;
X			return(-1);
X		}
X	}
X	else
X	{
X		if(param->pb[param->index++] == 0x29)   /* 0x29 == close parenthesis */
X			return(0);
X		else
X		{
X			--param->index;
X			return(-1);
X		}
X	}
X
X}   /* end of skip_paren */
X
X/*+----------------------------------------------------------------
X    get_alpha_zstr(&esd,&strbuf,strbuf_maxcb)
X    converts next alphabetic string token to upper case and places it
X    into the null-terminated 'strbuf' string.  returns 0 or -1
X    or skip_cmd_break error codes
X-----------------------------------------------------------------*/
Xint
Xget_alpha_zstr(param,strbuf,strbuf_maxcb)
Xregister ESD *param;
Xregister char *strbuf;
Xregister int strbuf_maxcb;
X{
X	register int izstr;
X	register int schar;
X	register char *param_ptr = param->pb;
X
X	if(izstr = skip_cmd_break(param))
X		return(izstr);
X	izstr = 0;
X	while( (izstr < strbuf_maxcb-1) && (param->index < param->cb) )
X	{
X		schar = param_ptr[param->index];
X		if( !isalpha(schar) )
X			break;
X		param->index++;
X		strbuf[izstr++] = to_upper(schar);
X	}
X
X	strbuf[izstr] = 0;		/* terminate the string for "C" anal retentives */
X	if(izstr)
X		return(0);
X	else /* decide whether to return badparam or noparam err */
X		return(-1);
X
X}   /* end of get_alpha_zstr */
X
X/*+----------------------------------------------------------------
X    get_alphanum_zstr(&esd,&strbuf,strbuf_maxcb)
X    converts next alphabetic string token to upper case and places it
X    into the null-terminated 'strbuf' string.  returns 0 or -1 
X    or skip_cmd_break error codes
X-----------------------------------------------------------------*/
Xint
Xget_alphanum_zstr(param,strbuf,strbuf_maxcb)
Xregister ESD *param;
Xregister char *strbuf;
Xregister int strbuf_maxcb;
X{
X	register int izstr = 0;
X	register int schar;
X
X	if(izstr = skip_cmd_break(param))
X		return(izstr);
X
X	while( (izstr < strbuf_maxcb-1) && (param->index < param->cb) )
X	{
X		schar = param->pb[param->index++];
X		if( isalnum(schar) )
X			strbuf[izstr++]=to_upper(schar);
X		else
X		{
X			--param->index;
X			break;
X		}
X	}
X
X	strbuf[izstr]=0;         /* terminate the string for "C" anal retentives */
X	if(strlen(strbuf))
X		return(0);
X	else /* decide whether to return badparam or noparam err */
X		return(-1);
X
X}   /* end of get_alphanum_zstr */
X
X/*+----------------------------------------------------------------
X    get_numeric_zstr(&esd,&strbuf,strbuf_maxcb)
X    gets next numeric string token places it
X    into the null-terminated 'strbuf' string.  returns 0 or -1 
X    or skip_cmd_break error codes
X-----------------------------------------------------------------*/
Xint
Xget_numeric_zstr(param,strbuf,strbuf_maxcb)
Xregister ESD *param;
Xregister char *strbuf;
Xregister int strbuf_maxcb;
X{
X	register int izstr;
X	register int schar;
X
X	if(izstr = skip_cmd_break(param))
X		return(izstr);
X
X	while( (izstr < strbuf_maxcb-1) && (param->index < param->cb) )
X	{
X		schar = param->pb[param->index++];
X		if( isdigit(schar) )
X			strbuf[izstr++]=schar;
X		else
X		{
X			--param->index;
X			break;
X		}
X	}
X
X	strbuf[izstr]=0;         /* terminate the string for "C" anal retentives */
X
X	if(strlen(strbuf))
X		return(0);
X	else /* decide whether to return badparam or noparam err */
X	{
X		return(skip_cmd_break(param));
X	}
X
X}   /* end of get_numeric_zstr */
X
X/*+----------------------------------------------------------------
X    get_word_zstr(&esd,&strbuf,strbuf_maxcb)
X    gets next word (continuous string of characters
X    without spacesor tabs )
X    returns 0 or -1 or skip_cmd_break error codes
X-----------------------------------------------------------------*/
Xint
Xget_word_zstr(param,strbuf,strbuf_maxcb)
Xregister ESD *param;
Xregister char *strbuf;
Xregister int strbuf_maxcb;
X{
X	register int izstr;
X	register int schar;
X
X	if(izstr = skip_cmd_break(param))
X		return(izstr);
X
X	while( (izstr < strbuf_maxcb-1) && (param->index < param->cb) )
X	{
X		schar = param->pb[param->index++];
X		if( (schar > 0x20) && (schar <= 0x7e))
X			strbuf[izstr++]=schar;
X		else
X		{
X			--param->index;
X			break;
X		}
X	}
X
X	strbuf[izstr]=0;         /* terminate the string for "C" anal retentives */
X
X	if(strlen(strbuf))
X		return(0);
X	else /* decide whether to return badparam or noparam err */
X	{
X		return(skip_cmd_break(param));
X	}
X
X}   /* end of get_word_zstr */
X
X/*+-----------------------------------------------------------------------
X	get_numeric_value(param,&long_var)
X------------------------------------------------------------------------*/
Xget_numeric_value(param,value)
Xregister ESD *param;
Xregister long *value;
X{
X	register int erc;
X	char	buf[32];
X
X	if(erc = get_numeric_zstr(param,buf,sizeof(buf)))
X		return(erc);
X	sscanf(buf,"%ld",value);
X	return(0);
X
X}	/* end of get_numeric_value */
X
X/*+-------------------------------------------------------------------------
X    strip_trailing_spaces_esd(tesd)
X--------------------------------------------------------------------------*/
Xvoid
Xstrip_trailing_spaces_esd(ztext)
Xregister ESD *ztext;
X{
X	while(ztext->cb && (ztext->pb[ztext->cb-1] == 0x20))
X		ztext->cb--;
X}   /* end of strip_trailing_spaces_esd */
X
X/*+-------------------------------------------------------------------------
X	fgetesd(&esd,fileptr)
X
X  stdio read from FILE *fileptr into esd
X  returns -1 on stdio error, -2 on line too long, 0 on success
X  returns tesd->cb set up not including trailing nl, tesd->index == 0
X--------------------------------------------------------------------------*/
Xint fgetesd(tesd,fileptr)
Xregister ESD *tesd;
Xregister FILE *fileptr;
X{
X	register char *cptr;
X
X	if(fgets(tesd->pb,tesd->maxcb,fileptr) == NULL)
X		return(-1);
X#if XENIX | MSDOS
X	if((cptr = strchr(tesd->pb,0x0A)) == NULL)
X		return(-2);
X#else
X	if((cptr = index(tesd->pb,0x0A)) == NULL)
X		return(-2);
X#endif
X	tesd->cb = (int)(cptr - tesd->pb);
X	null_terminate_esd(tesd);
X	tesd->index = 0;
X	tesd->old_index = 0;
X	return(0);
X
X}	/* end of fgetesd */
X
X/*+-------------------------------------------------------------------------
X	fputesd(&esd,fileptr,index_flag,nl_flag)
X
X  write esd contents to stdio FILE *fileptr
X  if index_flag is true, write from tesd->index thru end of esd
X  otherwise, from start of esd
X  if nl_flag is true, append nl to write, else just esd contents
X  returns -1 on stdio error, 0 on success
X--------------------------------------------------------------------------*/
Xint fputesd(tesd,fileptr,index_flag,nl_flag)
Xregister ESD *tesd;
Xregister FILE *fileptr;
Xint index_flag;
Xint nl_flag;
X{
X	register char *cptr;
X	register int write_length;
X
X	if(index_flag)
X	{
X		cptr = &tesd->pb[tesd->index];
X		write_length = tesd->cb - tesd->index;
X	}
X	else
X	{
X		cptr = tesd->pb;
X		write_length = tesd->cb;
X	}
X
X	if(write_length)
X		if(fwrite(cptr,write_length,1,fileptr) == 0)
X			return(-1);
X
X	if(nl_flag)
X		if(fputc(0x0A,fileptr) == 0)
X			return(-1);
X
X	return(0);
X}	/* end of fputesd */
X
X/*+-------------------------------------------------------------------------
X	cptr = skip_ld_break(cptr)
X  Skip leading spaces and tabs
X--------------------------------------------------------------------------*/
Xchar *skip_ld_break(zstr)
Xregister char *zstr;
X{
X	while((*zstr == 0x20) || (*zstr == 0x09))
X		zstr++;
X	return(zstr);
X}	/* end of skip_ld_break */
X
X/*+-----------------------------------------------------------------
X	append_zstr_to_esd
X------------------------------------------------------------------*/
Xappend_zstr_to_esd(tesd,zstr)
XESD		*tesd;
Xchar	*zstr;
X{
X	register int zstrlen = strlen(zstr);
X
X	if(zstrlen > (tesd->maxcb - tesd->cb))
X		zstrlen = tesd->maxcb - tesd->cb;
X
X	if(zstrlen)
X	{
X		strncpy(tesd->pb + tesd->cb,zstr,zstrlen);
X		tesd->cb += zstrlen;
X	}
X}
X/* end of esd2util.c */
X
X/* vi: set tabstop=4 shiftwidth=4: */
SHAR_EOF
chmod 0644 esd2util.c || echo "restore of esd2util.c fails"
exit 0
-- 
-------------------------------------------------------------------
Warren Tucker, Tridom Corporation       ...!gatech!emory!tridom!wht 
Sforzando (It., sfohr-tsahn'-doh).  A direction to perform the tone
or chord with special stress, or marked and sudden emphasis.



More information about the Comp.lang.c mailing list