/* * c s e t . c */ /*)LIBRARY */ #ifdef DOCUMENTATION title cset Make a character set from a string index Make a character set from a string index Make a temporary character set from a string index Define global parameters for csets synopsis #ifdef vms #include "c:cset.h" #else #include #endif CSET *cset(s) char s[]; CSET *cset_t(s) char s[]; extern int csmask; extern int cssize; extern int csunique; description Both cset() and cset_t() make a character set containing exactly the characters in the string passed, and return a pointer to it, or NULL if they couldn't allocate space. The difference between the two is that cset_t() does not reserve the space it has used - the next cset created will re-use the space used for the set created at this call. Hence, cset_t() should be used to create temporary cset's that can be discarded automatically. WARNING: Do NOT use cset_t() to construct an argument to a function, such as csjoin(), that can allocate a cset. Should that function have to make an allocation, it will clobber the temporary cset that you passed as an argument, with unpredictabel results. cset_t() is meant for use in functions like span() which only read csets. Note, however, that the cscomp() never creates a new cset, so calls like span(cscomp(cset_t("aeiou")) are safe. The trailing null on s will not be a member of the cset created. Defined within this module are three global parameters that can be set to modify the actions of the cset functions. cssize defines the size of a cset, i.e., the maximum number of distinct characters that can be members. (The members have numbers from 0 to cssize-1.) By default, cssize is 256 to support full 8-bit ASCII. Do not change cssize once you have created a cset, or unpredictable results will occur. csmask is a mask applied to characters before they are used as indices in the data arrays. It is defined because without such masking the sign extension of 8-bit ASCII characters when they are made into int's - when passed to functions, for example - would cause problems. By default, csmask is 0377, which keeps only the low byte. You might want to change it, probably to ~0, if you set cssize greater than 256; in this case, the string-oriented routines - like cset() - may not work properly if strings with characters whose ASCII codes are greater than 127 are passed. Note: csmask is only used where necessary to avoid sign-extension problems; it should not be viewed as a general-purpose "hook". Values of csmask other than 0377 or ~0 will yield unpredictable results. csunique, when TRUE, forces all cset operators, EXCEPT cscomp(), to return unique csets, rather than attempting to optimize (on both space and speed) by sharing existing data. This is mainly useful if you intend to use csets as general sets (with cswith() and csless()). By default, csunique is FALSE. WARNING: cscomp() is NOT sensitive to the value of csunique. You must use the real function, _cscomp(), which does test csunique. You might want to consider re-defining the macro form to call the function in this case. Note: csunique has no effect on cset_t(), which always returns a "temporary" cset. bugs author Jerry Leichter #endif /* )EDITLEVEL=18 * Edit history * 0.0 12-Jul-82 JSL Invention */ #ifdef vms #include "c:cset.h" #else #include #endif #define NULL 0 int cssize = 256; /* Size of character set table */ int csmask = 0377; /* Character mask */ int csunique = 0; /* No forced unique copies */ extern char *malloc(); static char *_table; /* Table to allocate from */ static char _mask = 0; /* Next mask to use */ static CSET *_cs = NULL; /* A CSET stored for use */ static CSET * _cset(s,keep) char *s; int keep; { register int i; register CSET *cs; register char mask; if (_mask == 0) /* Used up last table */ { _table = malloc(cssize); /* Get a new one */ if (_table == NULL) return(NULL); /* No room, sorry */ _mask = 1; /* From the top... */ } if ((cs = _cs) != NULL) /* Use saved one? */ _cs = NULL; /* Free it up */ else { cs = (CSET *)malloc(sizeof(CSET)); /* Must get a new one */ if (cs == NULL) return(NULL); /* No room, sorry */ } cs->_fill_ = 0; cs->mask = mask = _mask; cs->table = _table; for (i = 0; i < cssize; ) /* Clear the table */ cs->table[i++] &= ~mask; while (*s) cs->table[(unsigned)*s++] |= mask; /* Turn on our bits */ /* (must avoid sign */ /* extension) */ if (keep) _mask <<= 1; /* Next bit */ else _cs = cs; /* Save for later */ /* (reuse mask bit) */ return(cs); } CSET * cset(s) char s[]; { return(_cset(s,1)); } CSET * cset_t(s) char s[]; { return(_cset(s,0)); }