home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume18 / geneal / part02 / gconsist.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-03-08  |  6.1 KB  |  253 lines

  1. /* gconsist.c - consistency checker for geneal
  2.  * Written by Jim McBeath (jimmc) at SCI
  3.  *
  4.  * Revision history:
  5.  * 24-Jan-85    Jim McBeath    Initial definition
  6.  *  8-Mar-85    Jim McBeath    minor cleanups for lint
  7.  * 14.Sep.87  jimmc  Add address stuff
  8.  * 12.Dec.87  jimmc  Allow reference record type ('R')
  9.  * 19.Jan.88  jimmc  Use fgenum instead of enumIndex
  10.  */
  11.  
  12. #include <stdio.h>
  13. #include "geneal.h"
  14.  
  15. static int gconerrcount;    /* count of errors detected */
  16. static int gicount;        /* number of individuals */
  17. static int gfcount;        /* number of families */
  18. static int gacount;        /* number of addresses */
  19. static int gmcount;        /* number of males */
  20. static int gfmcount;        /* number of females */
  21.  
  22. /*..........*/
  23.  
  24. /* VARARGS1 */
  25. static
  26. dataerr(fmt,args)        /* print out a data error message */
  27. char *fmt;            /* printf style format list */
  28. int args;
  29. {
  30. char buf[1000];
  31.  
  32.     vsprintf(buf,fmt,&args);
  33.     printf("data error: %s\n", buf);
  34.     gconerrcount++;        /* count the error */
  35. }
  36.  
  37. /*..........*/
  38.  
  39. static int
  40. icmp(a,b)        /* compare two integers for qsort */
  41. int *a, *b;
  42. {
  43.     return (*a - *b);
  44. }
  45.  
  46. /*..........*/
  47.  
  48. static
  49. genumi(x)
  50. int x;
  51. {
  52. char sbuf[1000];
  53. int nlist[1000];
  54. int scount, ccount;
  55. int i;
  56. int pp;
  57. int addr;
  58.  
  59.     gicount++;        /* count the individual */
  60.     fgbstr(x,"SX",sbuf);    /* look at the sex */
  61.     if (strcmp(sbuf,"M")==0) gmcount++;
  62.     else if (strcmp(sbuf,"F")==0) gfmcount++;
  63.     pp = fgnum(x,"P");    /* see if parents */
  64.     if (pp>0)
  65.     {
  66.         ccount = fgbclist(pp,nlist);
  67.         if (ccount==0) dataerr(
  68.         "person %d claims family %d, which claims no children",
  69.         x, pp);
  70.         else
  71.         {
  72.         for (i=0; i<ccount; i++) if (nlist[i]==x) break;
  73.         if (i==ccount) dataerr(
  74.             "person %d claims family %d, but not vice-versa",
  75.             x, pp);
  76.         }
  77.     }
  78.     else ccount=0;
  79.     scount = fgbslist(x,nlist);    /* add spouse numbers */
  80.     if (scount>0)
  81.     {
  82.         for (i=0; i<scount; i++)    /* check each marriage/union */
  83.         {
  84.         if (x!=fgnum(nlist[i],"H") && x!=fgnum(nlist[i],"W"))
  85.             dataerr("person %d claims marriage %d but not vice-versa",
  86.             x, nlist[i]);
  87.         }
  88.         qsort((char*)nlist,scount,sizeof(nlist[0]),icmp);    /* sort list */
  89.         for (i=0; i<scount-1; i++) if (nlist[i]==nlist[i+1])
  90.         dataerr("duplicate marriage number %d in person %d",
  91.             nlist[i], x);
  92.     }
  93.     addr = fgnum(x,"ADDR");
  94.     if (addr>0) {
  95.         if (fgnum(addr,"WHO")!=x)
  96.           dataerr("person %d points to address %d, but not vice-versa",
  97.             x, addr);
  98.     }
  99. }
  100.  
  101. static
  102. genumf(x)
  103. int x;
  104. {
  105. char sbuf[1000];
  106. int nlist[1000];
  107. int scount, ccount;
  108. int i;
  109. int hh, ww;
  110. int addr;
  111.  
  112.      gfcount++;        /* count the family */
  113.     ccount = fgbclist(x,nlist);
  114.     if (ccount>0)
  115.     {
  116.         for (i=0; i<ccount; i++)    /* check children */
  117.         {
  118.         if (fgnum(nlist[i],"P")!=x)
  119.             dataerr("family %d claims child %d, but not vice-versa",
  120.             x, nlist[i]);
  121.         }
  122.         qsort((char*)nlist,ccount,sizeof(nlist[0]),icmp);
  123.         for (i=0; i<ccount-1; i++) if (nlist[i]==nlist[i+1])
  124.         dataerr("duplicate child %d in family %d", nlist[i], x);
  125.     }
  126.     hh = fgnum(x,"H");        /* check out the husband */
  127.     ww = fgnum(x,"W");        /* check out the wife */
  128.     for (i=0; i<ccount; i++)
  129.     {
  130.         if (hh>0 && nlist[i]==hh)
  131.         dataerr("person %d is both husband and child in family %d",
  132.             hh, x);
  133.         if (ww>0 && nlist[i]==ww)
  134.         dataerr("person %d is both wife and child in family %d",
  135.             ww, x);
  136.     }
  137.     if (hh>0)
  138.     {
  139.         if (ww==hh)
  140.         dataerr("family %d claims %d as both husband and wife",
  141.             x, hh);    /* not likely to happen, but what the heck */
  142.         fgbstr(hh,"SX",sbuf);    /* look at his sex */
  143.         if (strcmp(sbuf,"M")!=0)
  144.         dataerr(
  145. "family %d claims husband %d, who is not designated as a male", x, hh);
  146.         scount = fgbslist(hh,nlist);
  147.         for (i=0; i<scount; i++) if (nlist[i]==x) break;
  148.         if (i==scount)
  149.         dataerr("family %d claims husband %d, but not vice-versa",
  150.             x, hh);
  151.     }
  152.     if (ww>0)
  153.     {
  154.         fgbstr(ww,"SX",sbuf);    /* look at her sex */
  155.         if (strcmp(sbuf,"F")!=0)
  156.         dataerr(
  157. "family %d claims wife %d, who is not designated as a female", x, ww);
  158.         scount = fgbslist(ww,nlist);
  159.         for (i=0; i<scount; i++) if (nlist[i]==x) break;
  160.         if (i==scount)
  161.         dataerr("family %d claims wife %d, but not vice-versa",
  162.             x, ww);
  163.     }
  164.     addr = fgnum(x,"ADDR");
  165.     if (addr>0) {
  166.         if (fgnum(addr,"WHO")!=x)
  167.           dataerr("family %d points to address %d, but not vice-versa",
  168.             x, addr);
  169.     }
  170. }
  171.  
  172. static
  173. genuma(x)
  174. int x;
  175. {
  176. int who;
  177.  
  178.     gacount++;
  179.     who = fgnum(x,"WHO");
  180.     if (who<=0) dataerr("address %d has no WHO reference",x);
  181.     else if (fgnum(who,"ADDR")!=x)
  182.         dataerr("address %d points to %d, but not vice-versa",x,who);
  183. }
  184.  
  185. /* genum is the function which is called for each record.  It is what
  186.  * does the consistency checking.
  187.  */
  188.  
  189. /* ARGSUSED */
  190. int            /* returns 0 if OK */
  191. genum(x,d)        /* our enumeration function for enumIndex */
  192. int x;            /* the index number */
  193. int d;            /* its value */
  194. {
  195.  
  196.     if (x==0) return 0;    /* ignore record 0, it's just for comments */
  197.  
  198.     switch (fgtype(x)) {
  199.     case 'I':    /* individual */
  200.         genumi(x);
  201.         break;
  202.     case 'F':    /* family */
  203.         genumf(x);
  204.         break;
  205.     case 'A':    /* address */
  206.         genuma(x);
  207.         break;
  208.     case 'R':    /* reference */
  209.         /* nothing to check in this record type at the moment */
  210.         break;
  211.     default:
  212.         dataerr("bad type in record %d", x);
  213.         break;
  214.     }
  215.     return 0;            /* always continue */
  216. }
  217.  
  218. /*..........*/
  219.  
  220. /* gconsist is the top level consistency checker. */
  221.  
  222. int        /* returns 0 if OK */
  223. gconsist()        /* check the consistecny of the data */
  224. {
  225. int n;
  226.  
  227.     gfcount = gicount = gacount = gconerrcount = 0;    /* clear data */
  228.     printf("Checking data consistency...\n");
  229.     n = fgenum(genum);
  230.     if (n<0) printf("error enumerating indexes\n");
  231.     else    /* no errors, give report */
  232.     {
  233.         if (gconerrcount>0)
  234.             printf("%d data consistency error%s detected\n",
  235.                 gconerrcount, (gconerrcount==1?"":"s") );
  236.         else printf("No data consistency errors detected\n");
  237.         printf("%d individual%s, %d famil%s, %d address%s\n",
  238.             gicount, (gicount==1?"":"s"),
  239.             gfcount, (gfcount==1?"y":"ies"),
  240.             gacount, (gacount==1?"":"es") );
  241.         gicount -= (gmcount+gfmcount);
  242.             /* convert to count of unspeced */
  243.         printf("%d male%s, %d female%s, %d not indicated\n",
  244.             gmcount, (gmcount==1?"":"s"),
  245.             gfmcount, (gfmcount==1?"":"s"),
  246.             gicount, (gicount==1?"":"s") );
  247.     }
  248.     if (gconerrcount==0) return 0;    /* all OK */
  249.     else return 1;        /* error */
  250. }
  251.  
  252. /* end */
  253.