home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC Press 1997 July
/
Sezamfile97_1.iso
/
msdos
/
c
/
cbase11.a03
/
CBASE11.ZIP
/
XTEND
/
XSTRING.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-01
|
17KB
|
667 lines
/*
* Copyright (c) 1989-1992 Citadel Software, Inc.
* All Rights Reserved
*/
/* #ident "@(#)xstring.c 1.7 - 93/01/01" */
#include <port.h>
/* standard headers */
#include <ctype.h>
#include <errno.h>
#ifdef AC_STDDEF
#include <stddef.h>
#endif
#include <stdio.h>
#ifdef AC_STDLIB
#include <stdlib.h>
#endif
#ifdef AC_STRING
#include <string.h>
#endif
/* local headers */
#include "xtend.h"
/* manifest */
#ifdef AC_PROTO
int fmltolfm(char *t, const char *s, size_t n);
int lfmtofml(char *t, const char *s, size_t n);
size_t strnlen(const char *s, size_t n);
void xperror(const char *s);
const char * xstrerror(int errno);
#else
int fmltolfm();
int lfmtofml();
size_t strnlen();
void xperror();
const char * xstrerror();
#endif
extern const int
xsys_nerr;
extern const char * const
xsys_errlist[];
/* extensible system error list */
char const * const xsys_errlist[] = {
/* blkio library: 1..20 */
"too many block files open", /* BEMFILE */
"block file is not open", /* BENOPEN */
"buffering is off", /* BENBUF */
"buffering is on", /* BEBUF */
"block boundary error", /* BEBOUND */
"past end-of-file", /* BEEOF */
"no free list", /* BENFL */
"internal blkio error", /* BEFATAL */
NULL, /* 9 */
NULL, /* 10 */
NULL, /* 11 */
NULL, /* 12 */
NULL, /* 13 */
NULL, /* 14 */
NULL, /* 15 */
NULL, /* 16 */
NULL, /* 17 */
NULL, /* 18 */
NULL, /* 19 */
NULL, /* 20 */
/* lseq library: 21..40 */
"too many open lseqs", /* LSEMFILE */
"lseq is corrupt", /* LSECORRUPT */
"lseq is not open", /* LSENOPEN */
"buffering is off", /* LSENBUF */
"incorrect lock type", /* LSELOCK */
"no record", /* LSENREC */
"record boundary error", /* LSEBOUND */
"past end-of-file", /* LSEEOF */
"internal lseq error", /* LSEFATAL */
NULL, /* 30 */
NULL, /* 31 */
NULL, /* 32 */
NULL, /* 33 */
NULL, /* 34 */
NULL, /* 35 */
NULL, /* 36 */
NULL, /* 37 */
NULL, /* 38 */
NULL, /* 39 */
NULL, /* 40 */
/* btree library: 41..60 */
"too many open btrees", /* BTEMFILE */
"btree is corrupt", /* BTECORRUPT */
"btree is not open", /* BTENOPEN */
"buffering is off", /* BTENBUF */
"incorrect lock type", /* BTELOCK */
"no key", /* BTENKEY */
"duplicate key", /* BTEDUP */
"past end-of-file", /* BTEEOF */
"internal btree error", /* BTEFATAL */
NULL, /* 50 */
NULL, /* 51 */
NULL, /* 52 */
NULL, /* 53 */
NULL, /* 54 */
NULL, /* 55 */
NULL, /* 56 */
NULL, /* 57 */
NULL, /* 58 */
NULL, /* 59 */
NULL, /* 60 */
/* cbase library: 61..80 */
"too many open cbases", /* CBEMFILE */
"cbase is corrupt", /* CBECORRUPT */
"cbase is not open", /* CBENOPEN */
"incorrect lock type", /* CBELOCK */
"no record", /* CBENREC */
"no key", /* CBENKEY */
"duplicate", /* CBEDUP */
"text file error", /* CBEPRFILE */
"internal cbase error", /* CBEFATAL */
NULL, /* 70 */
NULL, /* 71 */
NULL, /* 72 */
NULL, /* 73 */
NULL, /* 74 */
NULL, /* 75 */
NULL, /* 76 */
NULL, /* 77 */
NULL, /* 78 */
NULL, /* 79 */
NULL, /* 80 */
};
/* number entries in extensible system error list */
const int xsys_nerr = nelems(xsys_errlist);
/* control macros */
#undef CVT_QUOTES /* switch to disable CVT_QUOTES processing */
/* macros */
/* maximum of two values */
#undef max
#define max(a,b) ((a) > (b) ? (a) : (b))
/* minimum of two values */
#undef min
#define min(a,b) ((a) < (b) ? (a) : (b))
/* macro to preserve characters within single and double quotes */
#ifdef CVT_QUOTES
#define QUOTES { \
char c = NUL; \
if (quotes && (*ps == '\'' || *ps == '\"')) { \
c = *ps; \
*pt++ = *ps++; \
while (pt < ttend) { \
*pt++ = *ps; \
if (*ps == c || *ps == NUL) break; \
} \
continue; \
} \
}
#else
#define QUOTES
#endif
/*man---------------------------------------------------------------------------
NAME
cvtss - convert string
SYNOPSIS
int cvtss(t, s, m, n)
char *t;
const char *s;
int m;
int n;
DESCRIPTION
The cvtss function takes the nul-terminated source string pointed
to by s, performs the conversions indicated by m, and places the
result in the target string pointed to by t. n is the size of
the target string. At most n characters are placed in t.
Values for m are constructed by bitwise OR-ing flags from the
following list. These macros are defined in basstr.h.
CVT_TP Trim the parity bit.
CVT_XSP Discard spaces and tabs.
CVT_XCTL Discard control characters.
CVT_XLEADSP Discard leading spaces and tabs.
CVT_1SP Reduce spaces and tabs to one space.
CVT_UPPER Convert lowercase to uppercase.
CVT_BTOP Convert [ to ( and ] to ).
CVT_XTRAILSP Discard trailing spaces and tabs.
CVT_QUOTES Do not alter characters inside single or
double quotes except for parity bit
trimming.
cvtss will fail if one or more of the following is true:
[EINVAL] t or s is the NULL pointer.
[EINVAL] n is less than 0.
DIAGNOSTICS
Upon successful completion, a value of 0 is returned. Otherwise,
a value of -1 is returned, and errno set to indicate the error.
NOTES
cvtss is adapted directly from the BASIC function CVT$$.
------------------------------------------------------------------------------*/
#ifdef AC_PROTO
int cvtss(char *t, const char *s, int m, int n)
#else
int cvtss(t, s, m, n)
char *t;
const char *s;
int m;
int n;
#endif
{
char * ts = NULL; /* temporary source string */
char * tt = NULL; /* temporary target string */
char PTR_HUGE *ttend= NULL; /* first char past end of tt */
int tn = 0; /* size of ts and tt */
#ifdef CVT_QUOTES
int quotes = 0; /* preserve quoted characters flag */
#endif
int bit = 0; /* bit number */
char PTR_HUGE *ps = NULL; /* pointer into ts */
char PTR_HUGE *pt = NULL; /* pointer into tt */
int flag = 0; /* gp flag */
/* validate arguments */
if (t == NULL || s == NULL || n < 0) {
errno = EINVAL;
return -1;
}
if (n < 1) {
return 0;
}
/* find size for ts */
tn = strlen(s) + 1;
tn = max(tn, n + 1);
/* create temporary strings */
ts = (char *)calloc((size_t)tn, sizeof(*ts));
if (ts == NULL) {
errno = ENOMEM;
return -1;
}
tt = (char *)calloc((size_t)tn, sizeof(*tt));
if (tt == NULL) {
free(ts);
errno = ENOMEM;
return -1;
}
ttend = (char PTR_HUGE *)tt + tn;
/* initialize ts with s */
strcpy(ts, s);
ts[tn - 1] = NUL;
/* perform conversions */
#ifdef CVT_QUOTES
quotes = m & CVT_QUOTES; /* set preserve quoted chars flag */
#endif
for (bit = 0; m != 0; ++bit, m >>= 1) {
if (!(m & 1)) {
continue;
}
switch (bit) {
case 0: /* trim the parity bit */
for (ps = ts, pt = tt; pt < ttend; ++ps) {
QUOTES;
*pt++ = *ps & 0x7F;
if (*ps == NUL) break;
}
break; /* case 0: */
case 1: /* discard all spaces and tabs */
for (ps = ts, pt = tt; pt < ttend; ++ps) {
QUOTES;
if (!(*ps == ' ' || *ps == '\t')) {
*pt++ = *ps;
}
if (*ps == NUL) break;
}
break; /* case 1: */
case 2: /* discard all control characters */
for (ps = ts, pt = tt; pt < ttend; ++ps) {
QUOTES;
if (*ps == '\t') {
*pt++ = ' ';
} else if (!iscntrl(*ps)) {
*pt++ = *ps;
}
if (*ps == NUL) break;
}
/* nul terminate if shorter than size */
if (pt < ttend) {
*pt++ = NUL;
}
break; /* case 2: */
case 3: /* discard leading spaces and tabs */
for (ps = ts; *ps == ' ' || *ps == '\t'; ++ps) {
}
strncpy(tt, (char *)ps, n);
break; /* case 3: */
case 4: /* reduce spaces and tabs to one space */
flag = 0;
for (ps = ts, pt = tt; pt < ttend; ++ps) {
QUOTES;
if (flag) {
if (*ps != ' ' && *ps != '\t') {
*pt++ = *ps;
flag = 0;
}
} else {
if (*ps == ' ' || *ps == '\t') {
*pt++ = ' ';
flag = 1;
} else {
*pt++ = *ps;
}
}
if (*ps == NUL) break;
}
break; /* case 4: */
case 5: /* convert lowercase to uppercase */
for (ps = ts, pt = tt; pt < ttend; ++ps) {
QUOTES;
*pt++ = toupper(*ps);
if (*ps == NUL) break;
}
break; /* case 5: */
case 6: /* convert [ to ( and ] to ) */
for (ps = ts, pt = tt; pt < ttend; ++ps) {
QUOTES;
if (*ps == '[') *pt = '(';
else if (*ps == ']') *pt = ')';
else *pt = *ps;
++pt;
if (*ps == NUL) break;
}
break; /* case 6: */
case 7: /* discard trailing spaces and tabs */
/* Note: Some DOS compilers become confused by the
* pointer arithmetic in this case, therefore a
* non-pointer version has been provided.
*/
#if OPSYS == OS_DOS /* non-pointer version for DOS */
{
int i;
for (i = (int)strnlen(ts, tn) - 1; i >= 0; --i) {
if (ts[i] != ' ' && ts[i] != '\t') break;
ts[i] = NUL;
}
}
#else /* normal pointer version */
for (ps = (char huge *)ts + len - 1; ps >= (char huge *)ts; --ps) {
if (*ps != ' ' && *ps != '\t') break;
}
ts[min(tn - 1, ps + 1 - (char huge *)ts)] = NUL;
#endif
strncpy(tt, ts, tn);
break; /* case 7: */
case 8: /* do not alter characters inside quotes */
/* see QUOTES macro */
continue;
break; /* case 8: */
default:
free(tt);
free(ts);
errno = EINVAL;
return -1;
break;
}
strncpy(ts, tt, tn);
}
/* load target string */
strncpy(t, ts, n);
/* free temporary strings */
free(tt);
free(ts);
return 0;
}
/*man---------------------------------------------------------------------------
NAME
fmltolfm - convert name from fml to lfm format
SYNOPSIS
int fmltolfm(t, s, n)
char *t;
const char *s;
size_t n;
DESCRIPTION
The fmltolfm function converts a name from the format "first
middle last" to "last first middle". s points to the
nul-terminated source string in fml format. t points to the
target string to receive the converted name. t and s may point
to the same string. There may be more than one middle name, or
the middle name may be absent. All leading and trailing spaces
must be removed from the source string before calling fmltolfm.
At most n characters are copied. The target will be padded with
nuls if the name has fewer than n characters.
fmltolfm will fail if one or more of the following is true:
[EINVAL] t or s is the NULL pointer.
SEE ALSO
lfmtofml.
DIAGNOSTICS
Upon successful completion, a value of 0 is returned. Otherwise,
a value of -1 is returned, and errno set to indicate the error.
------------------------------------------------------------------------------*/
#ifdef AC_PROTO
int fmltolfm(char *t, const char *s, size_t n)
#else
int fmltolfm(t, s, n)
char *t;
const char *s;
size_t n;
#endif
{
size_t len = 0; /* string length */
char * p = NULL;
char * ts = NULL; /* temporary string */
/* validate arguments */
if (t == NULL || s == NULL) {
errno = EINVAL;
return -1;
}
/* get length of name */
len = strlen(s);
/* find beginning of last name */
p = strrchr(s, ' ');
if (p == NULL) {
strncpy(t, s, n);
return 0;
}
/* create temporary string */
ts = (char *)calloc(n + 1, (size_t)1);
if (ts == NULL) {
errno = ENOMEM;
return -1;
}
/* perform conversion */
strncpy(ts, p + 1, n); /* copy last name */
ts[n] = NUL;
strncat(ts, " ", n - strlen(ts)); /* add space after last name */
ts[n] = NUL;
strncat(ts, s, n - strlen(ts)); /* copy beginning of name */
if (len < n) { /* remove space that marked last name */
ts[len] = NUL;
}
strncpy(t, ts, n); /* copy converted string to t */
/* free temporary string */
free(ts);
return 0;
}
/*man---------------------------------------------------------------------------
NAME
lfmtofml - convert name from lfm to fml format
SYNOPSIS
int lfmtofml(t, s, n)
char *t;
const char *s;
size_t n;
DESCRIPTION
The lfmtofml function converts a name from the format "last
first middle" to "first middle last". s points to the
nul-terminated source string in lfm format. t points to the
target string to receive the converted name. t and s may point
to the same string. There may be more than one middle name, or
the middle name may be absent. All leading and trailing spaces
must be removed from the source string before calling fmltolfm.
At most n characters are copied. The target will be padded with
nuls if the name has fewer than n characters.
lfmtofml will fail if one or more of the following is true:
[EINVAL] t or s is the NULL pointer.
SEE ALSO
fmltolfm.
DIAGNOSTICS
Upon successful completion, a value of 0 is returned. Otherwise,
a value of -1 is returned, and errno set to indicate the error.
------------------------------------------------------------------------------*/
#ifdef AC_PROTO
int lfmtofml(char *t, const char *s, size_t n)
#else
int lfmtofml(t, s, n)
char *t;
const char *s;
size_t n;
#endif
{
size_t len = 0; /* string length */
char * p = NULL;
char * ts = NULL; /* temporary string */
/* validate arguments */
if (t == NULL || s == NULL) {
errno = EINVAL;
return -1;
}
/* get length of name */
len = strlen(s);
/* find end of last name */
p = strchr(s, ' ');
if (p == NULL) {
strncpy(t, s, n);
return 0;
}
/* create temporary string */
ts = (char *)calloc(n + 1, (size_t)1);
if (ts == NULL) {
errno = ENOMEM;
return -1;
}
/* perform conversion */
strncpy(ts, p + 1, n); /* copy beginning of name */
ts[n] = NUL;
strncat(ts, " ", n - strlen(ts)); /* add space before last name */
ts[n] = NUL;
strncat(ts, s, n - strlen(ts)); /* copy last name */
if (len < n) { /* remove space that marked first name */
ts[len] = NUL;
}
strncpy(t, ts, n); /* copy converted string to t */
/* free temporary string */
free(ts);
return 0;
}
/*man---------------------------------------------------------------------------
NAME
strnlen - return length of string of size n
SYNOPSIS
size_t strnlen(s, n)
const char *s;
size_t n;
DESCRIPTION
SEE ALSO
------------------------------------------------------------------------------*/
#ifdef AC_PROTO
size_t strnlen(const char *s, size_t n)
#else
size_t strnlen(s, n)
const char *s;
size_t n;
#endif
{
size_t i;
for (i = 0; s[i] != NUL && i < n; ++i);
return i;
}
/*man---------------------------------------------------------------------------
NAME
SYNOPSIS
#include "xtend.h"
void xperror(s)
const char *s;
DESCRIPTION
SEE ALSO
------------------------------------------------------------------------------*/
#ifdef AC_PROTO
void xperror(const char *s)
#else
void xperror(s)
const char *s;
#endif
{
if (s == NULL) {
fprintf(stderr, "%s\n", xstrerror(errno));
} else if (*s == NUL) {
fprintf(stderr, "%s\n", xstrerror(errno));
} else {
fprintf(stderr, "%s: %s\n", s, xstrerror(errno));
}
return;
}
/*man---------------------------------------------------------------------------
NAME
SYNOPSIS
#include "xtend.h"
char *xstrerror(errno)
int errno;
DESCRIPTION
SEE ALSO
------------------------------------------------------------------------------*/
#ifdef AC_PROTO
const char *xstrerror(int errno)
#else
const char *xstrerror(errno)
int errno;
#endif
{
static char buf[81];
/* predefined error number */
if (errno >= 0) {
return strerror(errno);
}
/* extended error number */
if (abs(errno) <= xsys_nerr) {
if (xsys_errlist[abs(errno) - 1] != NULL) {
return xsys_errlist[abs(errno) - 1];
}
}
/* undefined error number */
sprintf(buf, "error number %d", errno);
buf[sizeof(buf) - 1] = NUL;
return buf;
}