home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 24 / CD_ASCQ_24_0995.iso / vrac / ged2ht23.zip / READ.C < prev    next >
C/C++ Source or Header  |  1995-07-14  |  7KB  |  259 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.  * Read in a GEDCOM file without interpreting the nodes
  36.  */
  37.  
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include <string.h>
  41. #include <errno.h>
  42. #include "node.h"
  43. #include "read.h"
  44. #include "tags.h"
  45.  
  46. long gedcom_lines;
  47. long current_lineno;
  48. char *current_gedcom;
  49.  
  50. #ifndef HAVE_FGETLN
  51. char *fgetln(FILE *f, size_t *size);
  52. #endif
  53.  
  54. struct node *
  55. newnode()
  56. {
  57.   struct node *n;
  58.   if((n = malloc(sizeof(*n))) == NULL)
  59.     out_of_memory();
  60.   memset(n, 0, sizeof(*n));
  61.   return(n);
  62. }
  63.  
  64. /*
  65.  * Read a series of GEDCOM lines at the same level, and chain them
  66.  * onto the given list.  If a line is encountered at a deeper level,
  67.  * then recurse.
  68.  *
  69.  * prev is a pointer to the previous sibling at the current level
  70.  */
  71.  
  72. struct node *
  73. read_gedcom(FILE *f, struct node *prev, int level)
  74. {
  75.   char *line, *rest, *levp, *xrefp, *tagp;
  76.   struct node *node = NULL;
  77.   struct tag *tp;
  78.   size_t size;
  79.  
  80.   while(prev && (line = fgetln(f, &size))) {
  81.     gedcom_lines++;
  82.     /*
  83.      * Allocate node and copy line into it
  84.      */
  85.     node = newnode();
  86.     node->lineno = ++current_lineno;
  87.     if((node->line = malloc(size+1)) == NULL)
  88.       out_of_memory();
  89.     node->line[size] = '\0';
  90.     do {
  91.       --size;
  92.       switch(line[size]) {
  93.       case '\n':
  94.       case '\r':
  95.     node->line[size] = '\0';
  96.     continue;
  97.     break;
  98.       default:
  99.     node->line[size] = line[size];
  100.     break;
  101.       }
  102.     } while(size);
  103.     line = node->line;
  104.     /*
  105.      * Figure out level number
  106.      */
  107.     rest = line;
  108.     while(*rest == ' ')
  109.       rest++;
  110.     if(*rest == '\0') {
  111.       free(node->line);
  112.       free(node);
  113.       continue;        /* Ignore blank line */
  114.     }
  115.     levp = rest;
  116.     while(*rest >= '0' && *rest <= '9')
  117.       rest++;
  118.     if(*rest != ' ') {
  119.       fprintf(stderr, "%s: %ld: Malformed GEDCOM line ignored\n",
  120.           current_gedcom, current_lineno);
  121.       free(node->line);
  122.       free(node);
  123.       continue;
  124.     }
  125.     *rest++ = '\0';
  126.     node->level = atoi(levp);
  127.     /*
  128.      * Extract XREF, if any
  129.      */
  130.     while(*rest == ' ')
  131.       rest++;
  132.     if(*rest == '\0') {
  133.       fprintf(stderr, "%s: %ld: Malformed GEDCOM line ignored\n",
  134.           current_gedcom, current_lineno);
  135.       free(node->line);
  136.       free(node);
  137.       continue;
  138.     }
  139.     if(*rest == '@') {
  140.       xrefp = ++rest;
  141.       while(*rest != '\0' && *rest != '@')
  142.     rest++;
  143.       if(*rest != '@') {
  144.     fprintf(stderr, "%s: %ld: Non-terminated cross-reference -- line ignored\n",
  145.         current_gedcom, current_lineno);
  146.     free(node->line);
  147.     free(node);
  148.     continue;
  149.       }
  150.       *rest++ = '\0';
  151.     } else {
  152.       xrefp = NULL;
  153.     }
  154.     node->xref = xrefp;
  155.     /*
  156.      * Extract tag
  157.      */
  158.     while(*rest == ' ')
  159.       rest++;
  160.     if(*rest == '\0') {
  161.       fprintf(stderr, "%s: %ld: Ignored GEDCOM line with no tag\n",
  162.           current_gedcom, current_lineno);
  163.       free(node->line);
  164.       free(node);
  165.       continue;
  166.     }
  167.     tagp = rest;
  168.     while(*rest != '\0' && *rest != ' ')
  169.       rest++;
  170.     if(*rest)
  171.       *rest++ = '\0';
  172.     if((tp = findtag(tagp, gedcom_tags, gedcom_tags_size)))
  173.       node->tag = tp;
  174.     while(*rest == ' ')
  175.       rest++;
  176.     node->rest = rest;
  177.     /*
  178.      * The line is parsed, now take care of linking it in to
  179.      * the data structure
  180.      */
  181.     if(node->level < level) {
  182.       return(node);
  183.     } else if(node->level == level) {
  184.       prev->siblings = node;
  185.       prev = node;
  186.       continue;
  187.     } else {
  188.       if(node->level > level+1)
  189.     fprintf(stderr, "%s: %ld: Level number increased by more than one\n",
  190.         current_gedcom, current_lineno);
  191.       prev->children = node;
  192.       node = read_gedcom(f, node, node->level);
  193.       if(node == NULL) {
  194.     fprintf(stderr, "%s: %ld GEDCOM file does not end at level 0\n",
  195.         current_gedcom, current_lineno);
  196.     return(NULL);
  197.       }
  198.       if(node->level < level)
  199.     return(node);
  200.       prev->siblings = node;
  201.       prev = prev->siblings;
  202.     }
  203.   }
  204.   if(!feof(f)) {
  205.     if(errno == ENOMEM)
  206.       out_of_memory();
  207.     else
  208.       fprintf(stderr, "%s: %ld: Error reading GEDCOM file\n",
  209.           current_gedcom, current_lineno);
  210.   }
  211.   return(NULL);
  212. }
  213.  
  214. void out_of_memory()
  215. {
  216.   fprintf(stderr, "Insufficient memory available for processing.\n");
  217.   exit(1);
  218. }
  219.                    
  220. #ifndef HAVE_FGETLN
  221. char *fgetln(FILE *f, size_t *size)
  222. {
  223.    static char *l = NULL;
  224.    char *lp, c;
  225.    static int max = 4;
  226.    int s = 0;
  227.    
  228.     
  229.    if(l == NULL) {
  230.      if((l = malloc(max)) == NULL)
  231.           out_of_memory();
  232.    }
  233.    if(feof(f) || ferror(f)) {
  234.      *size = 0;
  235.      return(NULL);
  236.    }
  237.    lp = l;
  238.    while((c = fgetc(f)) != EOF) {
  239.      if(s >= max-1) {
  240.         max = 2*max;
  241.         if((l = realloc(l, max)) == NULL)
  242.           out_of_memory();
  243.         lp = l + s;   
  244.      }
  245.      *lp++ = c;
  246.      s++;
  247.      if(c == '\n')
  248.         break;
  249.    }
  250.    *lp++ = '\0';
  251.    *size = s;
  252.    if(s == 0)
  253.      return(NULL);
  254.    return(l);
  255. }
  256. #endif
  257.  
  258.                    
  259.