Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!tut.cis.ohio-state.edu!rutgers!gatech!emory!dtscp1!tridom!wht From: wht@tridom.uucp (Warren Tucker) Newsgroups: comp.lang.c Subject: Re: strings Summary: a little long and NO warranty but this may help Message-ID: <118@tridom.uucp> Date: 16 May 89 18:00:50 GMT References: <10250@socslgw.csl.sony.JUNET> Organization: Tridom Corporation, Atlanta Lines: 634 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 X#include X#include "esd2.h" X X#if XENIX | MSDOS X#include 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.