/* * String utilities needed throughout the Hugs codebase. */ #include "prelude.h"#include "storage.h"#include "connect.h"#include "errors.h"#include "strutil.h"#include "char.h" /* -------------------------------------------------------------------------- * String manipulation routines: * ------------------------------------------------------------------------*/ String strCopy(s) /* make malloced copy of a string */String s; { if (s) { char *t; if ((t=(char *)malloc(strlen(s)+1))==0) { ERRMSG(0) "String storage space exhausted" EEND; } strcpy(t, s); return t; } return NULL;} String strnCopy(s,n) /* make malloced copy of a substring */String s;Int n; { if (s) { char *t; if ((Int)strlen(s) < n) n = strlen(s); if ((t=(char *)malloc(n+1))==0) { ERRMSG(0) "String storage space exhausted" EEND; } strncpy(t, s, n); t[n] = '\0'; return t; } return NULL;} /* Given a string containing a possibly qualified name, * split it up into a module and a name portion. */Void splitQualString(nm, pMod, pName) String nm;String* pMod;String* pName; { String dot; /* Find the last occurrence of '.' preceded by an identifier */ dot = nm + strlen(nm) - 1; while (dot != nm && !(*dot == '.' && isIn(dot[-1],IDAFTER))) dot--; if (dot == nm) { *pMod = NULL; *pName = nm; } else { /* The module portion consists of everything upto the last dot. */ *pMod = strnCopy(nm, dot - nm); /* Everything after the last '.' is the name string */ *pName = dot+1; }} /* Cheap&cheerful expandable strings / StringBuilders. * * Note: I'm willfully breaking the convention of using K&R style * function declarations here. Their time has come and gone. */struct StringBuilder { unsigned int len; unsigned int size; char* buf;}; #define INITIAL_BUILDER_SIZE 200 static Bool expandStringBuilder Args((StringBuilder* b, unsigned int newSz)); /* * Function: newStringBuilder(sz) * * Allocate a new StringBuilder object, giving its * initial buffer size 'sz'. If sz == 0, the initial size * is set to INITIAL_BUILDER_SIZE.. * */StringBuilder*newStringBuilder ( unsigned int sz ){ StringBuilder* b = (StringBuilder*)malloc(sizeof(StringBuilder)); if (!b) return NULL; b->size = ( sz == 0 ? INITIAL_BUILDER_SIZE : sz); b->len = 0; b->buf = (char*)malloc(sizeof(char)*b->size); if (!b->buf) { free(b); return NULL; } *(b->buf) = '\0'; return b;} /* * Function: expandStringBuilder(builder, newSz) * * Internal function for expanding a StringBuilder's internal * buffer to 'newSz'. Along with expansion the old contents of * the buffer is copied over. * * Returns TRUE if successful. */static BoolexpandStringBuilder(StringBuilder* b, unsigned int newSz){ char* buf; if (!b) return FALSE; if (b->size > newSz) return FALSE; buf = realloc(b->buf, newSz); if (!buf) return FALSE; b->size = newSz; b->buf = buf; return TRUE;} /* * Function: prependString(builder, str) * * The preferred usage mode for StringBuilders is to * concatenate stuff at the back, but prependString() * handles addition at the other end. * * Returns TRUE if successful. */BoolprependString(StringBuilder* b, char* str){ unsigned int len, newLen; if (!b) return FALSE; if (!str) return TRUE; len = strlen(str); newLen = b->len + len; if (len==0) return TRUE; if ( newLen >= b->size ) { unsigned int newSz = b->size*2; if ( newSz < newLen ) { newSz = newLen; } if ( !expandStringBuilder(b, newSz) ) { return FALSE; } } /* shift the buffer down to make room for 'str' */ memcpy(b->buf+len, b->buf, b->len+1); memcpy(b->buf, str, len-1); b->len = newLen; return TRUE;} /* * Function: appendString(builder, str) * * Append 'str' to the back of 'builder', expanding its * buffer to accommodate the added string, if needs be. * * Returns TRUE if successful. */BoolappendString(StringBuilder* b, char* str){ unsigned int len, newLen; if (!b) return FALSE; if (!str) return TRUE; len = strlen(str); newLen = b->len + len; if (len==0) return TRUE; if ( newLen >= b->size ) { unsigned int newSz = b->size*2; if ( newSz < newLen ) { newSz = newLen; } if ( !expandStringBuilder(b, newSz) ) { return FALSE; } } memcpy(b->buf+b->len,str,len+1); b->len = newLen; return TRUE;} /* * Function: appendStringFormat(builder, fmt, arg) * * This function provides an extremely limited form of * sprintf()-style format strings, allowing the substitution * of 'arg' zero or more times via the format string 'fmt': * * appendStringFormat(builder, "-P%s -Y%s", "foo"); * * is equivalent to * * appendString(builder, "-Pfoo -Yfoo"); * * Returns TRUE if successful. */BoolappendStringFormat(StringBuilder* b, char* fmt, char* arg){ char* prev = fmt; char* ptr = fmt; char tmp; if (!b) return FALSE; while ( (ptr = strchr(ptr, '%')) ) { /* Append verbatim text from the format string */ tmp = *ptr; *ptr = '\0'; appendString(b, prev); *ptr = tmp; if ( ptr[1] != '%' ) { /* Not an escaped occurrence of '%' */ switch (ptr[1]) { case 's': appendString(b, arg); ptr += 2; break; default: fprintf(stderr,"Unsupported format specifier, %%%c; ignoring", ptr[1]); ptr += 2; break; } } else { if (ptr[1] != '\0') { ptr += 2; } } prev = ptr; } appendString(b,prev); return TRUE;} /* * Function: toString(builder) * * Returns a pointer to the builder's internal buffer, i.e., * a copy is not made (=> the caller isn't passed the * responsibility of freeing the returned string.) * * */char*toString(StringBuilder* b){ if (!b) return NULL; return (b->buf);} /* * Function: freeStringBuilder(builder) * * Free up a StringBuilder object. */voidfreeStringBuilder(StringBuilder* b){ if (!b) return; if (b->buf) free(b->buf); b->buf = NULL; free(b);}
/*
* String utilities needed throughout the Hugs codebase.
*/
#include "prelude.h"
#include "storage.h"
#include "connect.h"
#include "errors.h"
#include "strutil.h"
#include "char.h"
/* --------------------------------------------------------------------------
* String manipulation routines:
* ------------------------------------------------------------------------*/
String strCopy(s) /* make malloced copy of a string */
String s; {
if (s) {
char *t;
if ((t=(char *)malloc(strlen(s)+1))==0) {
ERRMSG(0) "String storage space exhausted"
EEND;
}
strcpy(t, s);
return t;
}
return NULL;
}
String strnCopy(s,n) /* make malloced copy of a substring */
String s;
Int n; {
if (s) {
char *t;
if ((Int)strlen(s) < n)
n = strlen(s);
if ((t=(char *)malloc(n+1))==0) {
ERRMSG(0) "String storage space exhausted"
EEND;
}
strncpy(t, s, n);
t[n] = '\0';
return t;
}
return NULL;
}
/* Given a string containing a possibly qualified name,
* split it up into a module and a name portion.
*/
Void splitQualString(nm, pMod, pName)
String nm;
String* pMod;
String* pName; {
String dot;
/* Find the last occurrence of '.' preceded by an identifier */
dot = nm + strlen(nm) - 1;
while (dot != nm && !(*dot == '.' && isIn(dot[-1],IDAFTER)))
dot--;
if (dot == nm) {
*pMod = NULL;
*pName = nm;
} else {
/* The module portion consists of everything upto the last dot. */
*pMod = strnCopy(nm, dot - nm);
/* Everything after the last '.' is the name string */
*pName = dot+1;
}
}
/* Cheap&cheerful expandable strings / StringBuilders.
*
* Note: I'm willfully breaking the convention of using K&R style
* function declarations here. Their time has come and gone.
*/
struct StringBuilder {
unsigned int len;
unsigned int size;
char* buf;
};
#define INITIAL_BUILDER_SIZE 200
static Bool expandStringBuilder Args((StringBuilder* b, unsigned int newSz));
/*
* Function: newStringBuilder(sz)
*
* Allocate a new StringBuilder object, giving its
* initial buffer size 'sz'. If sz == 0, the initial size
* is set to INITIAL_BUILDER_SIZE..
*
*/
StringBuilder*
newStringBuilder ( unsigned int sz )
{
StringBuilder* b = (StringBuilder*)malloc(sizeof(StringBuilder));
if (!b) return NULL;
b->size = ( sz == 0 ? INITIAL_BUILDER_SIZE : sz);
b->len = 0;
b->buf = (char*)malloc(sizeof(char)*b->size);
if (!b->buf) {
free(b);
return NULL;
}
*(b->buf) = '\0';
return b;
}
/*
* Function: expandStringBuilder(builder, newSz)
*
* Internal function for expanding a StringBuilder's internal
* buffer to 'newSz'. Along with expansion the old contents of
* the buffer is copied over.
*
* Returns TRUE if successful.
*/
static Bool
expandStringBuilder(StringBuilder* b, unsigned int newSz)
{
char* buf;
if (!b) return FALSE;
if (b->size > newSz) return FALSE;
buf = realloc(b->buf, newSz);
if (!buf) return FALSE;
b->size = newSz;
b->buf = buf;
return TRUE;
}
/*
* Function: prependString(builder, str)
*
* The preferred usage mode for StringBuilders is to
* concatenate stuff at the back, but prependString()
* handles addition at the other end.
*
* Returns TRUE if successful.
*/
Bool
prependString(StringBuilder* b, char* str)
{
unsigned int len, newLen;
if (!b) return FALSE;
if (!str) return TRUE;
len = strlen(str);
newLen = b->len + len;
if (len==0) return TRUE;
if ( newLen >= b->size ) {
unsigned int newSz = b->size*2;
if ( newSz < newLen ) {
newSz = newLen;
}
if ( !expandStringBuilder(b, newSz) ) {
return FALSE;
}
}
/* shift the buffer down to make room for 'str' */
memcpy(b->buf+len, b->buf, b->len+1);
memcpy(b->buf, str, len-1);
b->len = newLen;
return TRUE;
}
/*
* Function: appendString(builder, str)
*
* Append 'str' to the back of 'builder', expanding its
* buffer to accommodate the added string, if needs be.
*
* Returns TRUE if successful.
*/
Bool
appendString(StringBuilder* b, char* str)
{
unsigned int len, newLen;
if (!b) return FALSE;
if (!str) return TRUE;
len = strlen(str);
newLen = b->len + len;
if (len==0) return TRUE;
if ( newLen >= b->size ) {
unsigned int newSz = b->size*2;
if ( newSz < newLen ) {
newSz = newLen;
}
if ( !expandStringBuilder(b, newSz) ) {
return FALSE;
}
}
memcpy(b->buf+b->len,str,len+1);
b->len = newLen;
return TRUE;
}
/*
* Function: appendStringFormat(builder, fmt, arg)
*
* This function provides an extremely limited form of
* sprintf()-style format strings, allowing the substitution
* of 'arg' zero or more times via the format string 'fmt':
*
* appendStringFormat(builder, "-P%s -Y%s", "foo");
*
* is equivalent to
*
* appendString(builder, "-Pfoo -Yfoo");
*
* Returns TRUE if successful.
*/
Bool
appendStringFormat(StringBuilder* b, char* fmt, char* arg)
{
char* prev = fmt;
char* ptr = fmt;
char tmp;
if (!b) return FALSE;
while ( (ptr = strchr(ptr, '%')) ) {
/* Append verbatim text from the format string */
tmp = *ptr;
*ptr = '\0';
appendString(b, prev);
*ptr = tmp;
if ( ptr[1] != '%' ) {
/* Not an escaped occurrence of '%' */
switch (ptr[1]) {
case 's': appendString(b, arg); ptr += 2; break;
default:
fprintf(stderr,"Unsupported format specifier, %%%c; ignoring", ptr[1]);
ptr += 2; break;
}
} else {
if (ptr[1] != '\0') {
ptr += 2;
}
}
prev = ptr;
}
appendString(b,prev);
return TRUE;
}
/*
* Function: toString(builder)
*
* Returns a pointer to the builder's internal buffer, i.e.,
* a copy is not made (=> the caller isn't passed the
* responsibility of freeing the returned string.)
*
*
*/
char*
toString(StringBuilder* b)
{
if (!b) return NULL;
return (b->buf);
}
/*
* Function: freeStringBuilder(builder)
*
* Free up a StringBuilder object.
*/
void
freeStringBuilder(StringBuilder* b)
{
if (!b) return;
if (b->buf) free(b->buf);
b->buf = NULL;
free(b);
}