home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 24 / CD_ASCQ_24_0995.iso / vrac / ged2ht23.zip / DATABASE.C < prev    next >
C/C++ Source or Header  |  1995-06-23  |  18KB  |  732 lines

  1. /*
  2.  * Copyright (c) 1995 Eugene W. Stark
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by Eugene W. Stark.
  16.  * 4. The name of the author may not be used to endorse or promote products
  17.  *    derived from this software without specific prior written permission.
  18.  * 5. No copying or redistribution in any form for commercial purposes is
  19.  *    permitted without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY EUGENE W. STARK (THE AUTHOR) ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
  25.  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  26.  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  27.  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. /*
  35.  * Build lineage-linked database from lines of GEDCOM file.
  36.  */
  37.  
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include <string.h>
  41. #include <ctype.h>
  42. #include "node.h"
  43. #include "database.h"
  44. #include "index.h"
  45. #include "tags.h"
  46.  
  47. /*
  48.  * Counts of various kinds of top-level records
  49.  */
  50.  
  51. int total_individuals;
  52. int total_families;
  53. int total_events;
  54. int total_sources;
  55. int total_notes;
  56. int total_repositories;
  57. int total_submitters;
  58.  
  59. /*
  60.  * Flag controlling capitalization of surnames
  61.  */
  62.  
  63. int capitalization = 1;
  64.  
  65. /*
  66.  * Arrays for each access to top-level records
  67.  */
  68.  
  69. struct individual_record **all_individuals;
  70. struct family_record **all_families;
  71.  
  72. /*
  73.  * Access to the hierarchical index tree
  74.  */
  75.  
  76. struct index_node *index_root;
  77. struct index_node *surname_head;
  78.  
  79. /*
  80.  * Parameters controlling production of index
  81.  */
  82.  
  83. int index_depth = 0;
  84. int index_width = 28;
  85.  
  86. void extract_xref(struct node *np);
  87. struct index_node *
  88. build_index(int level, struct individual_record *first,
  89.         struct index_node *prev, struct index_node *parent);
  90.  
  91. /*
  92.  * Pass I: Allocate database records and attach them to the GEDCOM nodes.
  93.  */
  94.  
  95. void
  96. process_records(struct node *np)
  97. {
  98.   for( ; np != NULL; np = np->siblings) {
  99.     if(np->tag == NULL)
  100.       continue;
  101.     switch(np->tag->value) {
  102.     case INDI:
  103.       total_individuals++;
  104.       process_individual_record(np);
  105.       break;
  106.     case FAM:
  107.       total_families++;
  108.       process_family_record(np);
  109.       break;
  110.     case EVEN:
  111.       total_events++;
  112.       process_event_record(np);
  113.       break;
  114.     case NOTE:
  115.       total_notes++;
  116.       process_note_record(np);
  117.       break;
  118.     case SOUR:
  119.       total_sources++;
  120.       process_source_record(np);
  121.       break;
  122.     case REPO:
  123.       total_repositories++;
  124.       process_repository_record(np);
  125.       break;
  126.     case SUBM:
  127.       total_submitters++;
  128.       process_submitter_record(np);
  129.       break;
  130.     default:
  131.       /* Skip unrecognized records */
  132.       break;
  133.     }
  134.   }
  135. }
  136.  
  137. void
  138. process_individual_record(struct node *np)
  139. {
  140.   struct individual_record *ip;
  141.   struct note_structure *ntp;
  142.   struct xref *xp;
  143.  
  144.   if((ip = malloc(sizeof(*ip))) == NULL)
  145.     out_of_memory();
  146.   memset(ip, 0, sizeof(*ip));
  147.   np->hook = ip;
  148.   ip->xref = np->xref;
  149.   index_enter(ip->xref, ip);
  150.   for(np = np->children ; np != NULL; np = np->siblings) {
  151.     if(np->tag == NULL)
  152.       continue;
  153.     switch(np->tag->value) {
  154.     case NAME:
  155.       ip->personal_name = process_name(np);
  156.       break;
  157.     case FAMS:
  158.       xp = process_xref(np);
  159.       if(ip->fams == NULL)
  160.     ip->fams = ip->lastfams = xp;
  161.       else {
  162.     ip->lastfams->next = xp;
  163.     ip->lastfams = xp;
  164.       }
  165.       break;
  166.     case FAMC:
  167.       xp = process_xref(np);
  168.       if(ip->famc == NULL)
  169.     ip->famc = ip->lastfamc = xp;
  170.       else {
  171.     ip->lastfamc->next = xp;
  172.     ip->lastfamc = xp;
  173.       }
  174.       break;
  175.     case SOUR:
  176.       xp = process_xref(np);
  177.       if(ip->sources == NULL)
  178.     ip->sources = ip->lastsource = xp;
  179.       else {
  180.     ip->sources->next = xp;
  181.     ip->lastsource = xp;
  182.       }
  183.       break;
  184.     case REFN:
  185.       ip->refn = np->rest;
  186.       break;
  187.     case RFN:
  188.       ip->rfn = np->rest;
  189.       break;
  190.     case AFN:
  191.       ip->afn = np->rest;
  192.       break;
  193.     case NOTE:
  194.       ntp = process_note(np);
  195.       if(ip->notes == NULL)
  196.     ip->notes = ip->lastnote = ntp;
  197.       else {
  198.     ip->lastnote->next = ntp;
  199.     ip->lastnote = ntp;
  200.       }
  201.       break;
  202.     case TITL:
  203.       ip->title = np->rest;
  204.       break;
  205.     case SEX:
  206.       if(*np->rest == 'M')
  207.     ip->sex = 'M';
  208.       else if(*np->rest == 'F')
  209.     ip->sex = 'F';
  210.       break;
  211.     case CENS: case MARR: case MARB: case MARC: case MARL: case MARS:
  212.     case ENGA: case BAPM: case BARM: case BASM: case BIRT: case BLES:
  213.     case BURI: case CHR: case CHRA: case CONF: case DEAT: case EMIG:
  214.     case GRAD: case IMMI: case NATU: case ORDN: case RETI: case PROB:
  215.     case WILL: case ANUL: case DIV: case DIVF:
  216.       if(ip->events == NULL)
  217.     ip->events = ip->lastevent = process_event(np);
  218.       else {
  219.     ip->lastevent->next = process_event(np);
  220.     ip->lastevent = ip->lastevent->next;
  221.       }
  222.       break;
  223.     default:
  224.       /* Skip unrecognized substructures */
  225.       break;
  226.     }
  227.   }
  228. }
  229.  
  230. void
  231. process_family_record(struct node *np)
  232. {
  233.   struct family_record *frp;
  234.   struct note_structure *ntp;
  235.   struct xref *xp;
  236.  
  237.   if((frp = malloc(sizeof(*frp))) == NULL)
  238.     out_of_memory();
  239.   memset(frp, 0, sizeof(*frp));
  240.   np->hook = frp;
  241.   frp->xref = np->xref;
  242.   index_enter(frp->xref, frp);
  243.   for(np = np->children ; np != NULL; np = np->siblings) {
  244.     if(np->tag == NULL)
  245.       continue;
  246.     switch(np->tag->value) {
  247.     case HUSB:
  248.       frp->husband = process_xref(np);
  249.       break;
  250.     case WIFE:
  251.       frp->wife = process_xref(np);
  252.       break;
  253.     case CHIL:
  254.       xp = process_xref(np);
  255.       if(frp->children == NULL)
  256.     frp->children = frp->lastchild = xp;
  257.       else {
  258.     frp->lastchild->next = xp;
  259.     frp->lastchild = xp;
  260.       }
  261.       break;
  262.     case SOUR:
  263.       xp = process_xref(np);
  264.       if(frp->sources == NULL)
  265.     frp->sources = frp->lastsource = xp;
  266.       else {
  267.     frp->sources->next = xp;
  268.     frp->lastsource = xp;
  269.       }
  270.       break;
  271.     case REFN:
  272.       frp->refn = np->rest;
  273.       break;
  274.     case CENS: case MARR: case MARB: case MARC: case MARL: case MARS:
  275.     case ENGA: case BAPM: case BARM: case BASM: case BIRT: case BLES:
  276.     case BURI: case CHR: case CHRA: case CONF: case DEAT: case EMIG:
  277.     case GRAD: case IMMI: case NATU: case ORDN: case RETI: case PROB:
  278.     case WILL: case ANUL: case DIV: case DIVF:
  279.       if(frp->events == NULL)
  280.     frp->events = frp->lastevent = process_event(np);
  281.       else {
  282.     frp->lastevent->next = process_event(np);
  283.     frp->lastevent = frp->lastevent->next;
  284.       }
  285.       break;
  286.     case NOTE:
  287.       ntp = process_note(np);
  288.       if(frp->notes == NULL)
  289.     frp->notes = frp->lastnote = ntp;
  290.       else {
  291.     frp->lastnote->next = ntp;
  292.     frp->lastnote = ntp;
  293.       }
  294.       break;
  295.     default:
  296.       /* Skip unrecognized substructures */
  297.       break;
  298.     }
  299.   }
  300. }
  301.  
  302. void
  303. process_source_record(struct node *np)
  304. {
  305.   struct source_record *sp;
  306.   struct continuation *cp = NULL;
  307.  
  308.   if((sp = malloc(sizeof(*sp))) == NULL)
  309.     out_of_memory();
  310.   memset(sp, 0, sizeof(*sp));
  311.   np->hook = sp;
  312.   sp->xref = np->xref;
  313.   index_enter(sp->xref, sp);
  314.   sp->text = np->rest;  /* Some GEDCOM's have the info after the SOUR */
  315.   for(np = np->children ; np != NULL; np = np->siblings) {
  316.     if(np->tag == NULL)
  317.       continue;
  318.     switch(np->tag->value) {  /* Other GEDCOM's have a full record */
  319.     case NAME:
  320.     case DATE:
  321.     case TITL:
  322.     case CONT:
  323.     case PLAC:
  324.     case REPO:
  325.     case AUTH:
  326.     case PUBL:
  327.       /*
  328.        * This treatment of source records is somewhat kludgy,
  329.        * but standards are lacking, and it makes the only examples
  330.        * I have of their use work OK.  I'll redo it someday when
  331.        * there is a clear standard.  Here we treat any of the
  332.        * above fields like text continuations, so that the data
  333.        * finds its way into the output, but isn't interpreted at all.
  334.        */
  335.       if(cp == NULL) {
  336.     if((sp->cont = malloc(sizeof(*sp->cont))) == NULL)
  337.       out_of_memory();
  338.     cp = sp->cont;
  339.       } else {
  340.     if((cp->next = malloc(sizeof(*cp->next))) == NULL)
  341.       out_of_memory();
  342.     cp = cp->next;
  343.       }
  344.       memset(cp, 0, sizeof(*cp));
  345.       np->hook = cp;
  346.       cp->text = np->rest;
  347.       break;
  348.     }
  349.   }
  350. }
  351.  
  352. void
  353. process_event_record(struct node *np)
  354. {
  355.  
  356. }
  357.  
  358. void
  359. process_note_record(struct node *np)
  360. {
  361.  
  362. }
  363.  
  364. void
  365. process_repository_record(struct node *np)
  366. {
  367.  
  368. }
  369.  
  370. void
  371. process_submitter_record(struct node *np)
  372. {
  373.  
  374. }
  375.  
  376. struct event_structure *
  377. process_event(struct node *np)
  378. {
  379.   struct event_structure *ep;
  380.   struct place_structure *pp;
  381.  
  382.   if((ep = malloc(sizeof(*ep))) == NULL)
  383.     out_of_memory();
  384.   memset(ep, 0, sizeof(*ep));
  385.   np->hook = ep;
  386.   ep->tag = np->tag;
  387.   for(np = np->children; np != NULL; np = np->siblings) {
  388.     if(np->tag == NULL)
  389.       continue;
  390.     switch(np->tag->value) {
  391.     case DATE:
  392.       ep->date = np->rest;
  393.       break;
  394.     case PLAC:
  395.       if((pp = malloc(sizeof(*pp))) == NULL)
  396.     out_of_memory();
  397.       memset(pp, 0, sizeof(*pp));
  398.       pp->name = np->rest;
  399.       ep->place = pp;
  400.       break;
  401.     default:
  402.       break;
  403.     }
  404.   }
  405.   return(ep);
  406. }
  407.  
  408. struct note_structure *
  409. process_note(struct node *np)
  410. {
  411.   struct note_structure *ntp;
  412.   struct continuation *ntpc = NULL;
  413.  
  414.   if((ntp = malloc(sizeof(*ntp))) == NULL)
  415.     out_of_memory();
  416.   memset(ntp, 0, sizeof(*ntp));
  417.   np->hook = ntp;
  418.   ntp->text = np->rest;
  419.   for(np = np->children; np != NULL; np = np->siblings) {
  420.     if(np->tag == NULL)
  421.       continue;
  422.     switch(np->tag->value) {
  423.     case CONT:
  424.       if(ntpc == NULL) {
  425.     if((ntp->cont = malloc(sizeof(*ntp->cont))) == NULL)
  426.       out_of_memory();
  427.     ntpc = ntp->cont;
  428.       } else {
  429.     if((ntpc->next = malloc(sizeof(*ntpc->next))) == NULL)
  430.       out_of_memory();
  431.     ntpc = ntpc->next;
  432.       }
  433.       memset(ntpc, 0, sizeof(*ntpc));
  434.       np->hook = ntpc;
  435.       ntpc->text = np->rest;
  436.       break;
  437.     default:
  438.       break;
  439.     }
  440.   }
  441.   return(ntp);
  442. }
  443.  
  444. struct xref *
  445. process_xref(struct node *np)
  446. {
  447.   struct xref *xp;
  448.  
  449.   extract_xref(np);
  450.   if((xp = malloc(sizeof(*xp))) == NULL)
  451.     out_of_memory();
  452.   memset(xp, 0, sizeof(*xp));
  453.   xp->id = np->rest;
  454.   return(xp);
  455. }
  456.  
  457. struct name_structure *
  458. process_name(struct node *np)
  459. {
  460.   char *cp, *p;
  461.   int i, surname=0;
  462.   struct name_structure *nsp;
  463.  
  464.   for(i = 0, cp = np->rest; *cp != '\0'; cp++, i++);
  465.   if((p = malloc(i+1)) == NULL)
  466.     out_of_memory();
  467.   if((nsp = malloc(sizeof(*nsp))) == NULL)
  468.     out_of_memory();
  469.   memset(nsp, 0, sizeof(*nsp));
  470.   nsp->name = p;
  471.   for(i = 0, cp = np->rest; *cp != '\0'; cp++, i++) {
  472.     if(*cp == '/') {
  473.       surname = 1 - surname;
  474.       if(surname)
  475.     nsp->surname_start = nsp->surname_end = i;
  476.       else
  477.     nsp->surname_end = i;
  478.       *p++ = ' ';
  479.       continue;
  480.     } else {
  481.       if(surname && capitalization)
  482.     *p++ = islower(*cp) ? toupper(*cp) : *cp;
  483.       else
  484.     *p++ = *cp;
  485.     }
  486.   }
  487.   *p = '\0';
  488.   if((nsp->surname = malloc(nsp->surname_end - nsp->surname_start + 1))
  489.      == NULL)
  490.       out_of_memory();
  491.   for(i = 0; i < nsp->surname_end - nsp->surname_start - 1; i++)
  492.       nsp->surname[i] = nsp->name[i + nsp->surname_start + 1];
  493.   nsp->surname[i] = '\0';
  494.   return(nsp);
  495. }
  496.  
  497. /*
  498.  * Pass II: Create lineage-linked structure on database nodes.
  499.  */
  500.  
  501. void
  502. link_records(struct node *np)
  503. {
  504.   struct individual_record **ip;
  505.   struct family_record **fp;
  506.   int i;
  507.  
  508.   if((ip = all_individuals = malloc(total_individuals *
  509.                sizeof(struct individual_record **))) == NULL)
  510.     out_of_memory();
  511.   if((fp = all_families = malloc(total_families *
  512.                sizeof(struct family_record **))) == NULL)
  513.     out_of_memory();
  514.   for( ; np != NULL; np = np->siblings) {
  515.     if(np->tag == NULL)
  516.       continue;
  517.     switch(np->tag->value) {
  518.     case INDI:
  519.       *ip++ = (struct individual_record *)np->hook;
  520.       link_individual_record(np);
  521.       break;
  522.     case FAM:
  523.       *fp++ = (struct family_record *)np->hook;
  524.       link_family_record(np);
  525.       break;
  526.     case SOUR:
  527.     case EVEN:
  528.     case NOTE:
  529.     case REPO:
  530.     case SUBM:
  531.     default:
  532.       /* Skip unrecognized records */
  533.       break;
  534.     }
  535.   }
  536.   qsort(all_individuals, total_individuals,
  537.     sizeof(struct individual_record *),
  538.     (int (*)(const void *, const void *)) compare_name);
  539.   /*
  540.    * Link individuals for the benefit of the output interpreter
  541.    */
  542.   for(i = 0; i < total_individuals-1; i++)
  543.     all_individuals[i]->next = all_individuals[i+1];
  544.   all_individuals[total_individuals-1]->next = NULL;
  545. }
  546.  
  547. void
  548. link_individual_record(struct node *np)
  549. {
  550.   struct individual_record *ip;
  551.   struct xref *xp;
  552.  
  553.   ip = (struct individual_record *)np->hook;
  554.   for(xp = ip->fams; xp != NULL; xp = xp->next)
  555.     xp->pointer.family = index_find(xp->id);
  556.   for(xp = ip->famc; xp != NULL; xp = xp->next)
  557.     xp->pointer.family = index_find(xp->id);
  558.   for(xp = ip->sources; xp != NULL; xp = xp->next)
  559.     xp->pointer.source = index_find(xp->id);
  560. }
  561.  
  562. void
  563. link_family_record(struct node *np)
  564. {
  565.   struct family_record *fp;
  566.   struct xref *xp;
  567.  
  568.   fp = (struct family_record *)np->hook;
  569.   if((xp = fp->husband))
  570.     xp->pointer.family = index_find(xp->id);
  571.   if((xp = fp->wife))
  572.     xp->pointer.family = index_find(xp->id);
  573.   for(xp = fp->children; xp != NULL; xp = xp->next)
  574.     xp->pointer.individual = index_find(xp->id);
  575. }
  576.  
  577. /*
  578.  * Compare personal names for lexicographic order.
  579.  * Used to sort individual records.
  580.  */
  581.  
  582. int compare_name(struct individual_record **ipp1,
  583.          struct individual_record **ipp2)
  584. {
  585.   char *p1, *p2, *ep1, *ep2;
  586.   struct individual_record *ip1 = *ipp1;
  587.   struct individual_record *ip2 = *ipp2;
  588.  
  589.   /*
  590.    * Handle case in which names are missing
  591.    */
  592.   if(ip1->personal_name == NULL) {
  593.     if(ip2->personal_name == NULL) {
  594.       return(0);
  595.     } else {
  596.       return(1);
  597.     }
  598.   } else if(ip2->personal_name == NULL) {
  599.     return(-1);
  600.   }
  601.   /*
  602.    * Normal case -- names present
  603.    */
  604.   p1 = ip1->personal_name->name + ip1->personal_name->surname_start;
  605.   p2 = ip2->personal_name->name + ip2->personal_name->surname_start;
  606.   ep1 = ip1->personal_name->name + ip1->personal_name->surname_end;
  607.   ep2 = ip2->personal_name->name + ip2->personal_name->surname_end;
  608.   while(p1 < ep1 && p2 < ep2) {
  609.     if(*p1 < *p2) {
  610.       return(-1);
  611.     }
  612.     if(*p1 > *p2) {
  613.       return(1);
  614.     }
  615.     p1++;
  616.     p2++;
  617.   }
  618.   if(p1 != ep1) {
  619.     return(-1);
  620.   } else if(p2 != ep2) {
  621.     return(1);
  622.   } else {
  623.     return(strcmp(ip1->personal_name->name, ip2->personal_name->name));
  624.   }
  625. }
  626.  
  627. /*
  628.  * Adjust np->rest in case an XREF constitutes the rest of the GEDCOM line
  629.  */
  630.  
  631. void
  632. extract_xref(struct node *np)
  633. {
  634.   char *cp;
  635.   if(*np->rest == '@') {
  636.     np->rest++;
  637.     for(cp = np->rest; *cp != '\0' && *cp != '@'; cp++);
  638.     *cp = '\0';
  639.   }
  640. }
  641.  
  642. /*
  643.  * Pass III: Build hierarchical index of individuals.
  644.  * This is a tree built on top of the list of individuals.
  645.  * Each node has "first" and "last" pointers, which indicate
  646.  * a range of individuals, and "children" pointers, which points
  647.  * to the head of a list of lower-level index nodes.
  648.  * There is one leaf index node for each individual, and for
  649.  * this node first == last and children == NULL.
  650.  */
  651.  
  652. void
  653. index_individuals()
  654. {
  655.     index_root = build_index(index_depth, all_individuals[0], NULL, NULL);
  656. }
  657.  
  658. struct index_node *
  659. build_index(int level, struct individual_record *first,
  660.         struct index_node *prev, struct index_node *parent)
  661. {
  662.     struct index_node *inp, *inc;
  663.     static int id = 0;
  664.     int i;
  665.  
  666.     if((inp = malloc(sizeof *inp)) == NULL)
  667.     out_of_memory();
  668.     memset(inp, 0, sizeof *inp);
  669.     inp->level = level;
  670.     inp->first = first;
  671.     inp->parent = parent;
  672.     inp->prev = prev;
  673.     if(level > 0) {
  674.     inp->id = id++;
  675.     inc = NULL;
  676.     for(i = 0; (index_width == 0 || i < index_width)
  677.                && first != NULL; i++) {
  678.         if(inc == NULL) {
  679.         inc = build_index(level-1, first, inc, inp);
  680.         inp->children = inc;
  681.         } else {
  682.         inc->next = build_index(level-1, first, inc, inp);
  683.         inc = inc->next;
  684.         }
  685.         first = inc->last->next;
  686.     }
  687.     if(inc != NULL)
  688.         inp->last = inc->last;
  689.     } else {
  690.     inp->last = first;
  691.     }
  692.     return(inp);
  693. }
  694.  
  695. /*
  696.  * Pass IV: Build surname index.
  697.  */
  698.  
  699. void index_surnames(struct index_node *inp)
  700. {
  701.     struct index_node *inc;
  702.     static struct index_node *prev = NULL;
  703.  
  704.     if(inp == NULL)
  705.     return;
  706.     if(inp->children != NULL) {
  707.     for(inc = inp->children; inc != NULL; inc = inc->next)
  708.         index_surnames(inc);
  709.     return;
  710.     }
  711.     if(prev != NULL
  712.        && inp->first->personal_name != NULL
  713.        && inp->first->personal_name->surname != NULL
  714.        && prev->first->personal_name != NULL
  715.        && prev->first->personal_name->surname != NULL
  716.        && !strcmp(inp->first->personal_name->surname,
  717.           prev->first->personal_name->surname)) {
  718.     prev->last = inp->last;
  719.     return;
  720.     }
  721.     if((inc = malloc(sizeof *inc)) == NULL)
  722.     out_of_memory();
  723.     memset(inc, 0, sizeof *inc);
  724.     inc->first = inc->last = inp->first;
  725.     inc->parent = inp->parent;
  726.     if(prev == NULL)
  727.     surname_head = inc;
  728.     else
  729.     prev->next = inc;
  730.     prev = inc;
  731. }
  732.