home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 24
/
CD_ASCQ_24_0995.iso
/
vrac
/
ged2ht23.zip
/
READ.C
< prev
next >
Wrap
C/C++ Source or Header
|
1995-07-14
|
7KB
|
259 lines
/*
* Copyright (c) 1995 Eugene W. Stark
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Eugene W. Stark.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
* 5. No copying or redistribution in any form for commercial purposes is
* permitted without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY EUGENE W. STARK (THE AUTHOR) ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Read in a GEDCOM file without interpreting the nodes
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "node.h"
#include "read.h"
#include "tags.h"
long gedcom_lines;
long current_lineno;
char *current_gedcom;
#ifndef HAVE_FGETLN
char *fgetln(FILE *f, size_t *size);
#endif
struct node *
newnode()
{
struct node *n;
if((n = malloc(sizeof(*n))) == NULL)
out_of_memory();
memset(n, 0, sizeof(*n));
return(n);
}
/*
* Read a series of GEDCOM lines at the same level, and chain them
* onto the given list. If a line is encountered at a deeper level,
* then recurse.
*
* prev is a pointer to the previous sibling at the current level
*/
struct node *
read_gedcom(FILE *f, struct node *prev, int level)
{
char *line, *rest, *levp, *xrefp, *tagp;
struct node *node = NULL;
struct tag *tp;
size_t size;
while(prev && (line = fgetln(f, &size))) {
gedcom_lines++;
/*
* Allocate node and copy line into it
*/
node = newnode();
node->lineno = ++current_lineno;
if((node->line = malloc(size+1)) == NULL)
out_of_memory();
node->line[size] = '\0';
do {
--size;
switch(line[size]) {
case '\n':
case '\r':
node->line[size] = '\0';
continue;
break;
default:
node->line[size] = line[size];
break;
}
} while(size);
line = node->line;
/*
* Figure out level number
*/
rest = line;
while(*rest == ' ')
rest++;
if(*rest == '\0') {
free(node->line);
free(node);
continue; /* Ignore blank line */
}
levp = rest;
while(*rest >= '0' && *rest <= '9')
rest++;
if(*rest != ' ') {
fprintf(stderr, "%s: %ld: Malformed GEDCOM line ignored\n",
current_gedcom, current_lineno);
free(node->line);
free(node);
continue;
}
*rest++ = '\0';
node->level = atoi(levp);
/*
* Extract XREF, if any
*/
while(*rest == ' ')
rest++;
if(*rest == '\0') {
fprintf(stderr, "%s: %ld: Malformed GEDCOM line ignored\n",
current_gedcom, current_lineno);
free(node->line);
free(node);
continue;
}
if(*rest == '@') {
xrefp = ++rest;
while(*rest != '\0' && *rest != '@')
rest++;
if(*rest != '@') {
fprintf(stderr, "%s: %ld: Non-terminated cross-reference -- line ignored\n",
current_gedcom, current_lineno);
free(node->line);
free(node);
continue;
}
*rest++ = '\0';
} else {
xrefp = NULL;
}
node->xref = xrefp;
/*
* Extract tag
*/
while(*rest == ' ')
rest++;
if(*rest == '\0') {
fprintf(stderr, "%s: %ld: Ignored GEDCOM line with no tag\n",
current_gedcom, current_lineno);
free(node->line);
free(node);
continue;
}
tagp = rest;
while(*rest != '\0' && *rest != ' ')
rest++;
if(*rest)
*rest++ = '\0';
if((tp = findtag(tagp, gedcom_tags, gedcom_tags_size)))
node->tag = tp;
while(*rest == ' ')
rest++;
node->rest = rest;
/*
* The line is parsed, now take care of linking it in to
* the data structure
*/
if(node->level < level) {
return(node);
} else if(node->level == level) {
prev->siblings = node;
prev = node;
continue;
} else {
if(node->level > level+1)
fprintf(stderr, "%s: %ld: Level number increased by more than one\n",
current_gedcom, current_lineno);
prev->children = node;
node = read_gedcom(f, node, node->level);
if(node == NULL) {
fprintf(stderr, "%s: %ld GEDCOM file does not end at level 0\n",
current_gedcom, current_lineno);
return(NULL);
}
if(node->level < level)
return(node);
prev->siblings = node;
prev = prev->siblings;
}
}
if(!feof(f)) {
if(errno == ENOMEM)
out_of_memory();
else
fprintf(stderr, "%s: %ld: Error reading GEDCOM file\n",
current_gedcom, current_lineno);
}
return(NULL);
}
void out_of_memory()
{
fprintf(stderr, "Insufficient memory available for processing.\n");
exit(1);
}
#ifndef HAVE_FGETLN
char *fgetln(FILE *f, size_t *size)
{
static char *l = NULL;
char *lp, c;
static int max = 4;
int s = 0;
if(l == NULL) {
if((l = malloc(max)) == NULL)
out_of_memory();
}
if(feof(f) || ferror(f)) {
*size = 0;
return(NULL);
}
lp = l;
while((c = fgetc(f)) != EOF) {
if(s >= max-1) {
max = 2*max;
if((l = realloc(l, max)) == NULL)
out_of_memory();
lp = l + s;
}
*lp++ = c;
s++;
if(c == '\n')
break;
}
*lp++ = '\0';
*size = s;
if(s == 0)
return(NULL);
return(l);
}
#endif