#include "gedcom_internal.h"
#include "gedcom.h"
+#include "buffer.h"
-#define INITIAL_BUF_SIZE 256
-char *mess_buffer = NULL;
-size_t bufsize;
+void cleanup_mess_buffer();
+struct safe_buffer mess_buffer = { NULL, 0, NULL, 0, cleanup_mess_buffer };
Gedcom_msg_handler msg_handler = NULL;
+/** This function registers a callback that is called if there are errors,
+ warnings or just messages coming from the parser. See
+ \ref Gedcom_msg_handler for the signature of the callback.
+
+ For errors, the \c msg passed to the callback will have the format:
+ \code
+ Error on line <lineno>: <actual_message>
+ \endcode
+ Note that the entire string will be properly internationalized, and
+ encoded in UTF-8 (<a href=encoding.html>Why UTF-8?</a>).
+ Also, no newline is appended, so that
+ the application program can use it in any way it wants. Warnings are
+ similar, but use "Warning" instead of "Error". Messages are plain
+ text, without any prefix.
+*/
void gedcom_set_message_handler(Gedcom_msg_handler func)
{
msg_handler = func;
}
-void reset_mess_buffer()
+void cleanup_mess_buffer()
{
- if (mess_buffer != NULL)
- mess_buffer[0] = '\0';
+ cleanup_buffer(&mess_buffer);
}
-void init_mess_buffer()
-{
- if (mess_buffer == NULL) {
- mess_buffer = (char *)malloc(INITIAL_BUF_SIZE);
- mess_buffer[0] = '\0';
- bufsize = INITIAL_BUF_SIZE;
- }
-}
-
-int safe_buf_vappend(char *s, va_list ap)
-{
- int res;
- int len;
- init_mess_buffer();
- len = strlen(mess_buffer);
- while (1) {
- char *buf_ptr = mess_buffer + len;
- int rest_size = bufsize - len;
-
- res = vsnprintf(buf_ptr, rest_size, s, ap);
-
- if (res > -1 && res < rest_size) {
- break;
- }
- else {
- bufsize *= 2;
- mess_buffer = realloc(mess_buffer, bufsize);
- }
- }
- return res;
-}
-
-int safe_buf_append(char *s, ...)
-{
- int res;
- va_list ap;
-
- va_start(ap, s);
- res = safe_buf_vappend(s, ap);
- va_end(ap);
-
- return res;
-}
-
-int gedcom_message(char* s, ...)
+int gedcom_message(const char* s, ...)
{
int res;
va_list ap;
va_start(ap, s);
- reset_mess_buffer();
- res = safe_buf_vappend(s, ap);
+ reset_buffer(&mess_buffer);
+ res = safe_buf_vappend(&mess_buffer, s, ap);
va_end(ap);
- safe_buf_append("\n");
if (msg_handler)
- (*msg_handler)(MESSAGE, mess_buffer);
+ (*msg_handler)(MESSAGE, get_buf_string(&mess_buffer));
return res;
}
-int gedcom_warning(char* s, ...)
+int gedcom_warning(const char* s, ...)
{
int res;
va_list ap;
- reset_mess_buffer();
- safe_buf_append("Warning on line %d: ", line_no);
+ reset_buffer(&mess_buffer);
+ if (line_no != 0)
+ safe_buf_append(&mess_buffer, _("Warning on line %d: "), line_no);
+ else
+ safe_buf_append(&mess_buffer, _("Warning: "));
va_start(ap, s);
- res = safe_buf_vappend(s, ap);
+ res = safe_buf_vappend(&mess_buffer, s, ap);
va_end(ap);
- safe_buf_append("\n");
if (msg_handler)
- (*msg_handler)(WARNING, mess_buffer);
+ (*msg_handler)(WARNING, get_buf_string(&mess_buffer));
return res;
}
-int gedcom_error(char* s, ...)
+int gedcom_error(const char* s, ...)
{
int res;
va_list ap;
- reset_mess_buffer();
- safe_buf_append("Error on line %d: ", line_no);
+ reset_buffer(&mess_buffer);
+ if (line_no != 0)
+ safe_buf_append(&mess_buffer, _("Error on line %d: "), line_no);
+ else
+ safe_buf_append(&mess_buffer, _("Error: "));
va_start(ap, s);
- res = safe_buf_vappend(s, ap);
+ res = safe_buf_vappend(&mess_buffer, s, ap);
va_end(ap);
- safe_buf_append("\n");
if (msg_handler)
- (*msg_handler)(ERROR, mess_buffer);
+ (*msg_handler)(ERROR, get_buf_string(&mess_buffer));
return res;
}
+
+void gedcom_mem_error(const char *filename, int line)
+{
+ gedcom_error(_("Could not allocate memory at %s, %d"), filename, line);
+}