xref.c \
age.c \
compat.c \
- buffer.c
-libgedcom_la_LDFLAGS = -export-dynamic -version-info $(LIBVERSION) $(LIBICONV)
+ buffer.c \
+ write.c
+libgedcom_la_LDFLAGS = -export-dynamic -version-info $(LIBVERSION)
libgedcom_la_LIBADD = calendar/libcalendar.la ../utf8/libutf8.la @INTLLIBS@
BUILT_SOURCES = lex.gedcom_1byte_.c \
lex.gedcom_hilo_.c \
xref.h \
age.h \
compat.h \
- buffer.h
+ buffer.h \
+ tag_data.h
EXTRA_DIST = gedcom.y \
gedcom_date.y \
gedcom_1byte.lex \
/* $Name$ */
#include <string.h>
-#include <iconv.h>
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#define GCONV_SEARCH_PATH "GCONV_PATH"
#define MAXBUF 255
-/*
-static iconv_t cd_to_internal = (iconv_t) -1;
-*/
-static ENCODING the_enc = ONE_BYTE;
+static Encoding the_enc = ONE_BYTE;
static hash_t *encodings = NULL;
const char* charwidth_string[] = { "1", "2_HILO", "2_LOHI" };
MEMORY_ERROR;
}
-char* get_encoding(const char* gedcom_n, ENCODING enc)
+char* get_encoding(const char* gedcom_n, Encoding enc)
{
char *key;
hnode_t *node;
+
+ if (encodings == NULL) return NULL;
key = (char*)malloc(strlen(gedcom_n) + strlen(charwidth_string[enc]) + 3);
if (buffer[strlen(buffer) - 1] != '\n') {
gedcom_error(_("Line too long in encoding configuration file '%s'"),
ENCODING_CONF_FILE);
+ line_no = 0;
return;
}
else if ((buffer[0] != '#') && (strcmp(buffer, "\n") != 0)) {
else {
gedcom_error(_("Missing data in encoding configuration file '%s'"),
ENCODING_CONF_FILE);
+ line_no = 0;
return;
}
}
}
+ line_no = 0;
if (fclose(in) != 0) {
gedcom_warning(_("Error closing file '%s': %s"),
ENCODING_CONF_FILE, strerror(errno));
}
}
-void set_encoding_width(ENCODING enc)
+void set_encoding_width(Encoding enc)
{
the_enc = enc;
}
#ifndef __ENCODING_H
#define __ENCODING_H
+#include "gedcom.h"
#include "utf8.h"
-typedef enum _ENC {
- ONE_BYTE = 0,
- TWO_BYTE_HILO = 1,
- TWO_BYTE_LOHI = 2
-} ENCODING;
-
int open_conv_to_internal(const char* fromcode);
void close_conv_to_internal();
char* to_internal(const char* str, size_t len, struct conv_buffer *output_buf);
void init_encodings();
-void set_encoding_width(ENCODING enc);
+char* get_encoding(const char* gedcom_n, Encoding enc);
+void set_encoding_width(Encoding enc);
void update_gconv_search_path();
#endif /* __ENCODING_H */
--- /dev/null
+/* Tag data header
+ Copyright (C) 2001,2002 The Genes Development Team
+ This file is part of the Gedcom parser library.
+ Contributed by Peter Verthez <Peter.Verthez@advalvas.be>, 2001.
+
+ The Gedcom parser library is free software; you can redistribute it
+ and/or modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The Gedcom parser library is distributed in the hope that it will be
+ useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the Gedcom parser library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/* $Id$ */
+/* $Name$ */
+
+#include "gedcom.h"
+
+typedef enum _OPT {
+ OPT_CONC = 0x01,
+ OPT_CONT = 0x02
+} Opt;
+
+struct tag_data {
+ char *elt_name;
+ char *tag_name;
+ int allowed_types;
+ Opt options;
+};
+
+struct tag_data tag_data[NR_OF_ELTS] =
+{
+ /* REC_HEAD */
+ { "REC_HEAD", "HEAD", GV_NULL, 0 },
+
+ /* REC_FAM */
+ { "REC_FAM", "FAM", GV_NULL, 0 },
+
+ /* REC_INDI */
+ { "REC_INDI", "INDI", GV_NULL, 0 },
+
+ /* REC_OBJE */
+ { "REC_OBJE", "OBJE", GV_NULL, 0 },
+
+ /* REC_NOTE */
+ { "REC_NOTE", "NOTE", GV_CHAR_PTR, 0 },
+
+ /* REC_REPO */
+ { "REC_REPO", "REPO", GV_NULL, 0 },
+
+ /* REC_SOUR */
+ { "REC_SOUR", "SOUR", GV_NULL, 0 },
+
+ /* REC_SUBN */
+ { "REC_SUBN", "SUBN", GV_NULL, 0 },
+
+ /* REC_SUBM */
+ { "REC_SUBM", "SUBM", GV_NULL, 0 },
+
+ /* REC_USER */
+ { "REC_USER", NULL, GV_NULL | GV_CHAR_PTR | GV_XREF_PTR, 0 },
+
+ /* ELT_HEAD_SOUR */
+ { "ELT_HEAD_SOUR", "SOUR", GV_CHAR_PTR, 0 },
+
+ /* ELT_HEAD_SOUR_VERS */
+ { "ELT_HEAD_SOUR_VERS", "VERS", GV_CHAR_PTR, 0 },
+
+ /* ELT_HEAD_SOUR_NAME */
+ { "ELT_HEAD_SOUR_NAME", "NAME", GV_CHAR_PTR, 0 },
+
+ /* ELT_HEAD_SOUR_CORP */
+ { "ELT_HEAD_SOUR_CORP", "CORP", GV_CHAR_PTR, 0 },
+
+ /* ELT_HEAD_SOUR_DATA */
+ { "ELT_HEAD_SOUR_DATA", "DATA", GV_CHAR_PTR, 0 },
+
+ /* ELT_HEAD_SOUR_DATA_DATE */
+ { "ELT_HEAD_SOUR_DATA_DATE", "DATE", GV_DATE_VALUE, 0 },
+
+ /* ELT_HEAD_SOUR_DATA_COPR */
+ { "ELT_HEAD_SOUR_DATA_COPR", "COPR", GV_CHAR_PTR, 0 },
+
+ /* ELT_HEAD_DEST */
+ { "ELT_HEAD_DEST", "DEST", GV_CHAR_PTR, 0 },
+
+ /* ELT_HEAD_DATE */
+ { "ELT_HEAD_DATE", "DATE", GV_DATE_VALUE, 0 },
+
+ /* ELT_HEAD_DATE_TIME */
+ { "ELT_HEAD_DATE_TIME", "TIME", GV_CHAR_PTR, 0 },
+
+ /* ELT_HEAD_SUBM */
+ { "ELT_HEAD_SUBM", "SUBM", GV_XREF_PTR, 0 },
+
+ /* ELT_HEAD_SUBN */
+ { "ELT_HEAD_SUBN", "SUBN", GV_XREF_PTR, 0 },
+
+ /* ELT_HEAD_FILE */
+ { "ELT_HEAD_FILE", "FILE", GV_CHAR_PTR, 0 },
+
+ /* ELT_HEAD_COPR */
+ { "ELT_HEAD_COPR", "COPR", GV_CHAR_PTR, 0 },
+
+ /* ELT_HEAD_GEDC */
+ { "ELT_HEAD_GEDC", "GEDC", GV_NULL, 0 },
+
+ /* ELT_HEAD_GEDC_VERS */
+ { "ELT_HEAD_GEDC_VERS", "VERS", GV_CHAR_PTR, 0 },
+
+ /* ELT_HEAD_GEDC_FORM */
+ { "ELT_HEAD_GEDC_FORM", "FORM", GV_CHAR_PTR, 0 },
+
+ /* ELT_HEAD_CHAR */
+ { "ELT_HEAD_CHAR", "CHAR", GV_CHAR_PTR, 0 },
+
+ /* ELT_HEAD_CHAR_VERS */
+ { "ELT_HEAD_CHAR_VERS", "VERS", GV_CHAR_PTR, 0 },
+
+ /* ELT_HEAD_LANG */
+ { "ELT_HEAD_LANG", "LANG", GV_CHAR_PTR, 0 },
+
+ /* ELT_HEAD_PLAC */
+ { "ELT_HEAD_PLAC", "PLAC", GV_NULL, 0 },
+
+ /* ELT_HEAD_PLAC_FORM */
+ { "ELT_HEAD_PLAC_FORM", "FORM", GV_CHAR_PTR, 0 },
+
+ /* ELT_HEAD_NOTE */
+ { "ELT_HEAD_NOTE", "NOTE", GV_CHAR_PTR, OPT_CONC | OPT_CONT }
+};
--- /dev/null
+/* Write functions for Gedcom.
+ Copyright (C) 2001,2002 The Genes Development Team
+ This file is part of the Gedcom parser library.
+ Contributed by Peter Verthez <Peter.Verthez@advalvas.be>, 2001.
+
+ The Gedcom parser library is free software; you can redistribute it
+ and/or modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The Gedcom parser library is distributed in the hope that it will be
+ useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the Gedcom parser library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/* $Id$ */
+/* $Name$ */
+
+#include "gedcom_internal.h"
+#include "gedcom.h"
+#include "encoding.h"
+#include "tag_data.h"
+#include "buffer.h"
+#include "utf8.h"
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+const char* encoding = "ASCII";
+int write_encoding_details = ONE_BYTE;
+/* SYS_NEWLINE is defined in config.h */
+const char* write_terminator = SYS_NEWLINE;
+
+struct Gedcom_write_struct {
+ int filedesc;
+ convert_t conv;
+ int total_conv_fails;
+ const char* term;
+ int ctxt_stack[MAXGEDCLEVEL+1];
+ int ctxt_level;
+};
+
+const char* default_encoding[] = {
+ /* ONE_BYTE */ "ASCII",
+ /* TWO_BYTE_HILO */ "UCS-2BE",
+ /* TWO_BYTE_LOHI */ "UCS-2LE"
+};
+
+const char* terminator[] = {
+ /* END_CR */ "\x0D",
+ /* END_LF */ "\x0A",
+ /* END_CR_LF */ "\x0D\x0A",
+ /* END_LF_CR */ "\x0A\x0D"
+};
+
+void cleanup_write_buffer();
+
+struct safe_buffer write_buffer = { NULL, 0, cleanup_write_buffer };
+
+void cleanup_write_buffer()
+{
+ cleanup_buffer(&write_buffer);
+}
+
+int write_simple(Gedcom_write_hndl hndl,
+ int level, char* xref, char* tag, char* value)
+{
+ int res;
+
+ if (hndl) {
+ char* converted;
+ int conv_fails;
+ size_t outlen;
+
+ reset_buffer(&write_buffer);
+ res = safe_buf_append(&write_buffer, "%d", level);
+ if (xref)
+ res += safe_buf_append(&write_buffer, " %s", xref);
+ res += safe_buf_append(&write_buffer, " %s", tag);
+ if (value)
+ res += safe_buf_append(&write_buffer, " %s", value);
+ res += safe_buf_append(&write_buffer, hndl->term);
+
+ converted = convert_from_utf8(hndl->conv, get_buf_string(&write_buffer),
+ &conv_fails, &outlen);
+
+ if (converted && (conv_fails == 0))
+ write(hndl->filedesc, converted, outlen);
+ else {
+ hndl->total_conv_fails += conv_fails;
+ gedcom_error
+ (_("Error converting output string: %s (%d conversion failures)"),
+ strerror(errno), conv_fails);
+ }
+ }
+ return 0;
+}
+
+int gedcom_write_set_encoding(const char* charset,
+ Encoding width, Enc_bom bom)
+{
+ char* new_encoding = NULL;
+ if (!strcmp(charset, "UNICODE")) {
+ if (width == ONE_BYTE) {
+ gedcom_error(_("Unicode cannot be encoded into one byte"));
+ return 1;
+ }
+ else {
+ new_encoding = get_encoding(charset, width);
+ if (new_encoding) {
+ encoding = new_encoding;
+ write_encoding_details = width | bom;
+ }
+ }
+ }
+ else {
+ new_encoding = get_encoding(charset, ONE_BYTE);
+ if (new_encoding) {
+ encoding = new_encoding;
+ write_encoding_details = ONE_BYTE;
+ }
+ }
+ return 0;
+}
+
+int gedcom_write_set_line_terminator(Enc_line_end end)
+{
+ write_terminator = terminator[end];
+ return 0;
+}
+
+Gedcom_write_hndl gedcom_write_open(const char *filename)
+{
+ Gedcom_write_hndl hndl;
+
+ hndl = (Gedcom_write_hndl)malloc(sizeof(struct Gedcom_write_struct));
+
+ if (!hndl)
+ MEMORY_ERROR;
+ else {
+ hndl->total_conv_fails = 0;
+ hndl->conv = initialize_utf8_conversion(encoding, 0);
+ if (!hndl->conv) {
+ gedcom_error(_("Could not open encoding '%s' for writing: %s"),
+ encoding, strerror(errno));
+ free(hndl);
+ hndl = NULL;
+ }
+ else {
+ hndl->filedesc = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
+ if (!hndl->filedesc) {
+ gedcom_error(_("Could not open file '%s' for writing: %s"),
+ filename, strerror(errno));
+ cleanup_utf8_conversion(hndl->conv);
+ free(hndl);
+ hndl = NULL;
+ }
+ else {
+ hndl->term = write_terminator;
+ hndl->ctxt_level = -1;
+ if (write_encoding_details & WITH_BOM) {
+ if (write_encoding_details & TWO_BYTE_HILO)
+ write(hndl->filedesc, "\xFE\xFF", 2);
+ else if (write_encoding_details & TWO_BYTE_LOHI)
+ write(hndl->filedesc, "\xFF\xFE", 2);
+ else
+ gedcom_warning(_("Byte order mark configured, but no Unicode"));
+ }
+ }
+ }
+ }
+
+ return hndl;
+}
+
+int gedcom_write_close(Gedcom_write_hndl hndl, int* total_conv_fails)
+{
+ int result = 0;
+ if (hndl) {
+ write_simple(hndl, 0, NULL, "TRLR", NULL);
+ if (total_conv_fails) *total_conv_fails = hndl->total_conv_fails;
+ result = close(hndl->filedesc);
+ cleanup_utf8_conversion(hndl->conv);
+ free(hndl);
+ }
+ return result;
+}
+
+char* get_tag_string(int elt_or_rec, char* tag)
+{
+ char* result = tag_data[elt_or_rec].tag_name;
+
+ if (result)
+ return result;
+ else if (tag)
+ return tag;
+ else {
+ gedcom_error(_("The element or record type '%s' requires a specific tag"
+ "for writing"),
+ tag_data[elt_or_rec].elt_name);
+ return NULL;
+ }
+}
+
+int check_type(int elt_or_rec, Gedcom_val_type type)
+{
+ int allowed = tag_data[elt_or_rec].allowed_types;
+ if (allowed & type)
+ return 1;
+ else {
+ gedcom_error(_("Wrong data type for writing element or record type '%s'"),
+ tag_data[elt_or_rec].elt_name);
+ return 0;
+ }
+}
+
+int get_level(Gedcom_write_hndl hndl, int elt_or_rec, int parent)
+{
+ if (parent == -1) {
+ hndl->ctxt_level = 0;
+ }
+ else {
+ while (hndl->ctxt_level && hndl->ctxt_stack[hndl->ctxt_level] != parent)
+ hndl->ctxt_level--;
+ if (hndl->ctxt_stack[hndl->ctxt_level] == parent) {
+ hndl->ctxt_level++;
+ }
+ else {
+ gedcom_error(_("Parent %d not found during write of %d"),
+ parent, elt_or_rec);
+ return -1;
+ }
+ }
+ hndl->ctxt_stack[hndl->ctxt_level] = elt_or_rec;
+ return hndl->ctxt_level;
+}
+
+int gedcom_write_record_str(Gedcom_write_hndl hndl,
+ Gedcom_rec rec, char* tag,
+ struct xref_value* xref, char* val)
+{
+ int result = 1;
+ int level = 0;
+ char* tag_str = NULL;
+ char* xref_str = NULL;
+
+ tag_str = get_tag_string(rec, tag);
+ level = get_level(hndl, rec, -1);
+ if (tag_str && check_type(rec, (val ? GV_CHAR_PTR : GV_NULL))) {
+ if (xref)
+ xref_str = xref->string;
+ result = write_simple(hndl, level, xref_str, tag_str, val);
+ }
+
+ return result;
+}
+
+int gedcom_write_element_str(Gedcom_write_hndl hndl,
+ Gedcom_elt elt, char* tag, int parent_rec_or_elt,
+ char* val)
+{
+ int result = 1;
+ int level = -1;
+ char* tag_str = NULL;
+
+ tag_str = get_tag_string(elt, tag);
+ level = get_level(hndl, elt, parent_rec_or_elt);
+ if (tag_str && (level != -1)
+ && check_type(elt, (val ? GV_CHAR_PTR : GV_NULL))) {
+ result = write_simple(hndl, level, NULL, tag_str, val);
+ }
+
+ return result;
+}