home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Monster Media 1994 #1
/
monster.zip
/
monster
/
PROG_C
/
RECIO110.ZIP
/
TESTCH.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-03-28
|
10KB
|
304 lines
/* testch.c - tests int, double, char and string char delimited functions */
/* recio version 1.10, release March 28, 1994 */
/* Copyright (C) 1994 William Pierpoint */
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "recio.h"
/* errors normally to stderr; but for test, stdout */
#define errout stdout
/* clip value v between lower l and upper u bounds */
#define range(l, v, u) (min(max((l),(v)),(u)))
/****************************************************************************
Dynamic string copy function, kludged for use with recio. This
function is not part of recio nor was rseterr() designed to work
with it, but you get the idea.
Obligation: free dst when finished with it.
*****************************************************************************/
char * /* return dst */
scopys( /* copy string dynamically */
char *dst, /* destination string pointer */
char *src) /* source string pointer */
/****************************************************************************/
{
size_t dlen; /* strlen of dst */
size_t slen; /* strlen of src */
int errnum; /* error number */
/* if null src pointer */
if (!src) {
rseterr(NULL, EINVAL);
dst = NULL;
goto done;
}
if (dst) {
dlen = strlen(dst);
slen = strlen(src);
if (dlen < slen) {
do {
dst = (char *) realloc(dst, slen+1);
if (!dst) {
errnum = rseterr(NULL, ENOMEM);
if (errnum) goto done;
}
} while (!dst);
}
strcpy(dst, src);
} else {
do {
dst = strdup(src);
if (!dst) {
errnum = rseterr(NULL, ENOMEM);
if (errnum) goto done;
}
} while (!dst);
}
done:
return dst;
}
/****************************************************************************/
void /* returns nothing */
rdaterrmsg( /* print data error message */
REC *rp, /* record pointer */
int errnum) /* error number */
/****************************************************************************/
{
switch (errnum) {
case R_ERANGE: /* data out of range */
fprintf(errout, "DATA ERROR reading %s at record %lu and field %d: "
"data value out of range\n", rnames(rp), rrecno(rp), rfldno(rp));
break;
case R_EINVDAT: /* invalid data */
fprintf(errout, "DATA ERROR reading %s at record %lu and field %d: "
"invalid data\n", rnames(rp), rrecno(rp), rfldno(rp));
break;
case R_EMISDAT: /* missing data */
fprintf(errout, "DATA ERROR reading %s at record %lu and field %d: "
"data missing\n", rnames(rp), rrecno(rp), rfldno(rp));
break;
}
}
/****************************************************************************/
void /* returns nothing */
rerrfn( /* recio callback error function */
REC *rp) /* record pointer */
/****************************************************************************/
{
int errnum; /* error number */
char strbuf[33]; /* string buffer for ltoa and sprintf */
if (risvalid(rp)) {
/* reof flag set */
if (reof(rp)) {
fprintf(errout, "ERROR reading %s: "
"tried to read past end of file\n", rnames(rp));
/* rerror flag set */
} else {
/* determine cause of error */
errnum = rerror(rp);
switch (errnum) {
/* data errors */
case R_ERANGE: /* data out of range */
case R_EINVDAT: /* invalid data */
case R_EMISDAT: /* missing data */
rdaterrmsg(rp, errnum);
/* determine context */
switch (rcxtno(rp)) {
case RECIN:
/* determine field */
switch (rfldno(rp)) {
case 1: /* the integer field */
switch (errnum) {
case R_EMISDAT:
fprintf(errout, "...substituting zero\n");
rsetfldstr(rp, "0");
break;
case R_EINVDAT:
case R_ERANGE:
fprintf(errout, "...substituting best guess\n");
rsetfldstr(rp, ltoa(
(int) range(INT_MIN, strtol(rflds(rp), NULL, 10), INT_MAX),
strbuf, 10));
break;
}
break;
case 2: /* the double field */
switch (errnum) {
case R_EMISDAT:
fprintf(errout, "...substituting zero\n");
rsetfldstr(rp, "0");
break;
case R_EINVDAT:
case R_ERANGE:
fprintf(errout, "...substituting best guess\n");
sprintf(strbuf, "%g", strtod(rflds(rp), NULL));
rsetfldstr(rp, strbuf);
break;
}
break;
case 3: /* the character field */
switch (errnum) {
case R_EMISDAT:
fprintf(errout, "...substituting the letter N\n");
rsetfldstr(rp, "N");
break;
case R_EINVDAT:
fprintf(errout, "...substituting best guess\n");
strbuf[0] = strtoc(rflds(rp), NULL);
strbuf[1] = '\0';
rsetfldstr(rp, strbuf);
break;
}
break;
case 4: /* the string field */
switch (errnum) {
case R_EMISDAT:
fprintf(errout, "...substituting empty field\n");
rsetfldstr(rp, "");
break;
}
break;
default: /* all other fields */
break;
}
break;
default: /* programming error - missing context number */
fprintf (errout, "FATAL ERROR in %s: missing context number\n",
rnames(rp));
abort();
break;
}
break;
/* non-fatal errors */
case R_ENOREG:
fprintf(errout, "WARNING: function atexit failed\n");
rclearerr(rp);
break;
/* fatal errors (R_EINVAL, R_ENOMEM) */
case R_EINVAL:
fprintf(errout, "FATAL ERROR reading FILE %s: invalid argument",
rnames(rp));
abort();
break;
case R_ENOMEM:
fprintf(errout, "FATAL ERROR reading FILE %s: out of memory",
rnames(rp));
abort();
break;
default:
fprintf(errout, "FATAL ERROR reading FILE %s: unknown error",
rnames(rp));
abort();
break;
}
}
/* invalid record pointer */
} else {
switch (errno) {
/* non-fatal errors */
case EACCES:
case EMFILE:
fprintf(errout, "WARNING: %s\n", strerror(errno));
break;
/* fatal errors (EINVAL, ENOMEM) */
default:
fprintf(errout, "FATAL ERROR: %s\n", strerror(errno));
abort();
break;
}
errno = 0;
}
}
/****************************************************************************
main
*****************************************************************************/
#include <io.h>
int main()
{
int fldint; /* integer field */
double flddbl; /* double field */
int fldch; /* character field */
char *fldstr = NULL; /* string field */
int hstdin = fileno(stdin); /* handle to stdin */
/* install error function */
rseterrfn(rerrfn);
/* set field and text delimiters */
rsetfldch(recin, ',');
rsettxtch(recin, '"');
/* if input not redirected */
if (isatty(hstdin)) {
/* print instructions */
puts("RECIO v 1.10 TESTCH Copyright (C) 1994 William Pierpoint");
puts("Tests integer, double, character, and string character "
"delimited functions.");
puts("It reads four fields, separated by commas, from the console.");
puts("Example:");
puts(" 1, 3.14 , Y, \"Hello, World!\"\n");
puts("Press Ctrl-Z followed by the Enter key to exit program.");
puts("You may begin now.\n");
}
/* loop through input */
while (rgetrec(recin)) {
/* if input redirected, echo record contents */
if (!isatty(hstdin)) puts(rrecs(recin));
/* parse record */
fldint = rgeti(recin);
flddbl = rgetd(recin);
fldch = rgetc(recin);
fldstr = scopys(fldstr, rgets(recin));
/* print results */
printf("\n");
printf(" Integer field: %d\n", fldint);
printf(" Double field: %g\n", flddbl);
printf("Character field: %c\n", fldch);
printf(" String field: %s\n\n", fldstr);
}
/* free string fields */
free (fldstr);
/* check stream for error */
if (rerror(recin)) {
fprintf(errout, "ERROR reading %s ended on error: %s",
rnames(recin), strerror(rerror(recin)));
exit (EXIT_FAILURE);
}
return EXIT_SUCCESS;
}