home *** CD-ROM | disk | FTP | other *** search
- /* gconsist.c - consistency checker for geneal
- * Written by Jim McBeath (jimmc) at SCI
- *
- * Revision history:
- * 24-Jan-85 Jim McBeath Initial definition
- * 8-Mar-85 Jim McBeath minor cleanups for lint
- * 14.Sep.87 jimmc Add address stuff
- * 12.Dec.87 jimmc Allow reference record type ('R')
- * 19.Jan.88 jimmc Use fgenum instead of enumIndex
- */
-
- #include <stdio.h>
- #include "geneal.h"
-
- static int gconerrcount; /* count of errors detected */
- static int gicount; /* number of individuals */
- static int gfcount; /* number of families */
- static int gacount; /* number of addresses */
- static int gmcount; /* number of males */
- static int gfmcount; /* number of females */
-
- /*..........*/
-
- /* VARARGS1 */
- static
- dataerr(fmt,args) /* print out a data error message */
- char *fmt; /* printf style format list */
- int args;
- {
- char buf[1000];
-
- vsprintf(buf,fmt,&args);
- printf("data error: %s\n", buf);
- gconerrcount++; /* count the error */
- }
-
- /*..........*/
-
- static int
- icmp(a,b) /* compare two integers for qsort */
- int *a, *b;
- {
- return (*a - *b);
- }
-
- /*..........*/
-
- static
- genumi(x)
- int x;
- {
- char sbuf[1000];
- int nlist[1000];
- int scount, ccount;
- int i;
- int pp;
- int addr;
-
- gicount++; /* count the individual */
- fgbstr(x,"SX",sbuf); /* look at the sex */
- if (strcmp(sbuf,"M")==0) gmcount++;
- else if (strcmp(sbuf,"F")==0) gfmcount++;
- pp = fgnum(x,"P"); /* see if parents */
- if (pp>0)
- {
- ccount = fgbclist(pp,nlist);
- if (ccount==0) dataerr(
- "person %d claims family %d, which claims no children",
- x, pp);
- else
- {
- for (i=0; i<ccount; i++) if (nlist[i]==x) break;
- if (i==ccount) dataerr(
- "person %d claims family %d, but not vice-versa",
- x, pp);
- }
- }
- else ccount=0;
- scount = fgbslist(x,nlist); /* add spouse numbers */
- if (scount>0)
- {
- for (i=0; i<scount; i++) /* check each marriage/union */
- {
- if (x!=fgnum(nlist[i],"H") && x!=fgnum(nlist[i],"W"))
- dataerr("person %d claims marriage %d but not vice-versa",
- x, nlist[i]);
- }
- qsort((char*)nlist,scount,sizeof(nlist[0]),icmp); /* sort list */
- for (i=0; i<scount-1; i++) if (nlist[i]==nlist[i+1])
- dataerr("duplicate marriage number %d in person %d",
- nlist[i], x);
- }
- addr = fgnum(x,"ADDR");
- if (addr>0) {
- if (fgnum(addr,"WHO")!=x)
- dataerr("person %d points to address %d, but not vice-versa",
- x, addr);
- }
- }
-
- static
- genumf(x)
- int x;
- {
- char sbuf[1000];
- int nlist[1000];
- int scount, ccount;
- int i;
- int hh, ww;
- int addr;
-
- gfcount++; /* count the family */
- ccount = fgbclist(x,nlist);
- if (ccount>0)
- {
- for (i=0; i<ccount; i++) /* check children */
- {
- if (fgnum(nlist[i],"P")!=x)
- dataerr("family %d claims child %d, but not vice-versa",
- x, nlist[i]);
- }
- qsort((char*)nlist,ccount,sizeof(nlist[0]),icmp);
- for (i=0; i<ccount-1; i++) if (nlist[i]==nlist[i+1])
- dataerr("duplicate child %d in family %d", nlist[i], x);
- }
- hh = fgnum(x,"H"); /* check out the husband */
- ww = fgnum(x,"W"); /* check out the wife */
- for (i=0; i<ccount; i++)
- {
- if (hh>0 && nlist[i]==hh)
- dataerr("person %d is both husband and child in family %d",
- hh, x);
- if (ww>0 && nlist[i]==ww)
- dataerr("person %d is both wife and child in family %d",
- ww, x);
- }
- if (hh>0)
- {
- if (ww==hh)
- dataerr("family %d claims %d as both husband and wife",
- x, hh); /* not likely to happen, but what the heck */
- fgbstr(hh,"SX",sbuf); /* look at his sex */
- if (strcmp(sbuf,"M")!=0)
- dataerr(
- "family %d claims husband %d, who is not designated as a male", x, hh);
- scount = fgbslist(hh,nlist);
- for (i=0; i<scount; i++) if (nlist[i]==x) break;
- if (i==scount)
- dataerr("family %d claims husband %d, but not vice-versa",
- x, hh);
- }
- if (ww>0)
- {
- fgbstr(ww,"SX",sbuf); /* look at her sex */
- if (strcmp(sbuf,"F")!=0)
- dataerr(
- "family %d claims wife %d, who is not designated as a female", x, ww);
- scount = fgbslist(ww,nlist);
- for (i=0; i<scount; i++) if (nlist[i]==x) break;
- if (i==scount)
- dataerr("family %d claims wife %d, but not vice-versa",
- x, ww);
- }
- addr = fgnum(x,"ADDR");
- if (addr>0) {
- if (fgnum(addr,"WHO")!=x)
- dataerr("family %d points to address %d, but not vice-versa",
- x, addr);
- }
- }
-
- static
- genuma(x)
- int x;
- {
- int who;
-
- gacount++;
- who = fgnum(x,"WHO");
- if (who<=0) dataerr("address %d has no WHO reference",x);
- else if (fgnum(who,"ADDR")!=x)
- dataerr("address %d points to %d, but not vice-versa",x,who);
- }
-
- /* genum is the function which is called for each record. It is what
- * does the consistency checking.
- */
-
- /* ARGSUSED */
- int /* returns 0 if OK */
- genum(x,d) /* our enumeration function for enumIndex */
- int x; /* the index number */
- int d; /* its value */
- {
-
- if (x==0) return 0; /* ignore record 0, it's just for comments */
-
- switch (fgtype(x)) {
- case 'I': /* individual */
- genumi(x);
- break;
- case 'F': /* family */
- genumf(x);
- break;
- case 'A': /* address */
- genuma(x);
- break;
- case 'R': /* reference */
- /* nothing to check in this record type at the moment */
- break;
- default:
- dataerr("bad type in record %d", x);
- break;
- }
- return 0; /* always continue */
- }
-
- /*..........*/
-
- /* gconsist is the top level consistency checker. */
-
- int /* returns 0 if OK */
- gconsist() /* check the consistecny of the data */
- {
- int n;
-
- gfcount = gicount = gacount = gconerrcount = 0; /* clear data */
- printf("Checking data consistency...\n");
- n = fgenum(genum);
- if (n<0) printf("error enumerating indexes\n");
- else /* no errors, give report */
- {
- if (gconerrcount>0)
- printf("%d data consistency error%s detected\n",
- gconerrcount, (gconerrcount==1?"":"s") );
- else printf("No data consistency errors detected\n");
- printf("%d individual%s, %d famil%s, %d address%s\n",
- gicount, (gicount==1?"":"s"),
- gfcount, (gfcount==1?"y":"ies"),
- gacount, (gacount==1?"":"es") );
- gicount -= (gmcount+gfmcount);
- /* convert to count of unspeced */
- printf("%d male%s, %d female%s, %d not indicated\n",
- gmcount, (gmcount==1?"":"s"),
- gfmcount, (gfmcount==1?"":"s"),
- gicount, (gicount==1?"":"s") );
- }
- if (gconerrcount==0) return 0; /* all OK */
- else return 1; /* error */
- }
-
- /* end */
-