summaryrefslogtreecommitdiff
path: root/libasm/asm_error.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2005-07-26 05:00:05 +0000
committerUlrich Drepper <drepper@redhat.com>2005-07-26 05:00:05 +0000
commitb08d5a8fb42f4586d756068065186b5af7e48dad (patch)
tree9f05f86be7877ed461b4dc05f53b29ea4fc0d2a1 /libasm/asm_error.c
downloadelfutils-b08d5a8fb42f4586d756068065186b5af7e48dad.tar.gz
Adjust for monotone.
Diffstat (limited to 'libasm/asm_error.c')
-rw-r--r--libasm/asm_error.c183
1 files changed, 183 insertions, 0 deletions
diff --git a/libasm/asm_error.c b/libasm/asm_error.c
new file mode 100644
index 00000000..9d2d81ed
--- /dev/null
+++ b/libasm/asm_error.c
@@ -0,0 +1,183 @@
+/* Error handling in libasm.
+ Copyright (C) 2002, 2004 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libintl.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include "libasmP.h"
+
+
+/* This is the key for the thread specific memory. */
+static tls_key_t key;
+
+/* The error number. Used in non-threaded programs. */
+static int global_error;
+static bool threaded;
+/* We need to initialize the thread-specific data. */
+once_define (static, once);
+
+/* The initialization and destruction functions. */
+static void init (void);
+static void free_key_mem (void *mem);
+
+
+int
+asm_errno (void)
+{
+ int result;
+
+ /* If we have not yet initialized the buffer do it now. */
+ once_execute (once, init);
+
+ if (threaded)
+ {
+ /* We have a key. Use it to get the thread-specific buffer. */
+ int *buffer = getspecific (key);
+ if (buffer == NULL)
+ {
+ /* No buffer allocated so far. */
+ buffer = (int *) malloc (sizeof (int));
+ if (buffer == NULL)
+ /* No more memory available. We use the static buffer. */
+ buffer = &global_error;
+
+ setspecific (key, buffer);
+
+ *buffer = 0;
+ }
+
+ result = *buffer;
+ *buffer = ASM_E_NOERROR;
+ return result;
+ }
+
+ result = global_error;
+ global_error = ASM_E_NOERROR;
+ return result;
+}
+
+
+void
+__libasm_seterrno (value)
+ int value;
+{
+ /* If we have not yet initialized the buffer do it now. */
+ once_execute (once, init);
+
+ if (threaded)
+ {
+ /* We have a key. Use it to get the thread-specific buffer. */
+ int *buffer = getspecific (key);
+ if (buffer == NULL)
+ {
+ /* No buffer allocated so far. */
+ buffer = malloc (sizeof (int));
+ if (buffer == NULL)
+ /* No more memory available. We use the static buffer. */
+ buffer = &global_error;
+
+ setspecific (key, buffer);
+ }
+
+ *buffer = value;
+ }
+
+ global_error = value;
+}
+
+
+/* Return the appropriate message for the error. */
+static const char *msgs[ASM_E_NUM] =
+{
+ [ASM_E_NOERROR] = N_("no error"),
+ [ASM_E_NOMEM] = N_("out of memory"),
+ [ASM_E_CANNOT_CREATE] = N_("cannot create output file"),
+ [ASM_E_INVALID] = N_("invalid parameter"),
+ [ASM_E_CANNOT_CHMOD] = N_("cannot change mode of output file"),
+ [ASM_E_CANNOT_RENAME] = N_("cannot rename output file"),
+ [ASM_E_DUPLSYM] = N_("duplicate symbol"),
+ [ASM_E_TYPE] = N_("invalid section type for operation")
+};
+
+const char *
+asm_errmsg (error)
+ int error;
+{
+ int last_error;
+
+ /* If we have not yet initialized the buffer do it now. */
+ once_execute (once, init);
+
+ if ((error == 0 || error == -1) && threaded)
+ {
+ /* We have a key. Use it to get the thread-specific buffer. */
+ int *buffer = (int *) getspecific (key);
+ if (buffer == NULL)
+ {
+ /* No buffer allocated so far. */
+ buffer = (int *) malloc (sizeof (int));
+ if (buffer == NULL)
+ /* No more memory available. We use the static buffer. */
+ buffer = &global_error;
+
+ setspecific (key, buffer);
+ *buffer = 0;
+ }
+
+ last_error = *buffer;
+ }
+ else
+ last_error = global_error;
+
+ if (error < -1)
+ return _("Unknown error");
+ if (error == 0 && last_error == 0)
+ /* No error. */
+ return NULL;
+
+ if (error != -1)
+ last_error = error;
+
+ if (last_error == ASM_E_LIBELF)
+ return elf_errmsg (-1);
+
+ return _(msgs[last_error]);
+}
+
+
+/* Free the thread specific data, this is done if a thread terminates. */
+static void
+free_key_mem (void *mem)
+{
+ free (mem);
+ setspecific (key, NULL);
+}
+
+
+/* Initialize the key for the global variable. */
+static void
+init (void)
+{
+ // XXX Screw you, gcc4, the unused function attribute does not work.
+ __asm ("" :: "r" (free_key_mem));
+
+ if (key_create (&key, free_key_mem) == 0)
+ /* Creating the key succeeded. */
+ threaded = true;
+}