summaryrefslogtreecommitdiff
path: root/backend/dvi/mdvi-lib/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'backend/dvi/mdvi-lib/util.c')
-rw-r--r--backend/dvi/mdvi-lib/util.c550
1 files changed, 550 insertions, 0 deletions
diff --git a/backend/dvi/mdvi-lib/util.c b/backend/dvi/mdvi-lib/util.c
new file mode 100644
index 00000000..349d273a
--- /dev/null
+++ b/backend/dvi/mdvi-lib/util.c
@@ -0,0 +1,550 @@
+/*
+ * Copyright (C) 2000, Matias Atria
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "private.h"
+
+static char *const messages[] = {
+ _G("Ooops!"),
+ _G("Aieeeee!!"),
+ _G("Ouch!"),
+ _G("Houston, we have a problem"),
+ _G("3.. 2.. 1.. BOOM!"),
+ _G("I'm history"),
+ _G("I'm going down"),
+ _G("I smell a rat")
+};
+#define NMSGS (sizeof(messages) / sizeof(char *))
+
+static FILE *logfile = NULL;
+static int _mdvi_log_level;
+
+int mdvi_set_logfile(const char *filename);
+int mdvi_set_logstream(FILE *file);
+int mdvi_set_loglevel(int level);
+
+static void vputlog(int level, const char *head, const char *format, va_list ap)
+{
+ if(logfile != NULL && _mdvi_log_level >= level) {
+ if(head != NULL)
+ fprintf(logfile, "%s: ", head);
+ vfprintf(logfile, format, ap);
+ }
+}
+
+int mdvi_set_logfile(const char *filename)
+{
+ FILE *f = NULL;
+
+ if(filename && (f = fopen(filename, "w")) == NULL)
+ return -1;
+ if(logfile != NULL && !isatty(fileno(logfile))) {
+ fclose(logfile);
+ logfile = NULL;
+ }
+ if(filename)
+ logfile = f;
+ return 0;
+}
+
+int mdvi_set_logstream(FILE *file)
+{
+ if(logfile && !isatty(fileno(logfile))) {
+ fclose(logfile);
+ logfile = NULL;
+ }
+ logfile = file;
+ return 0;
+}
+
+int mdvi_set_loglevel(int level)
+{
+ int old = _mdvi_log_level;
+
+ _mdvi_log_level = level;
+ return old;
+}
+
+#ifndef NODEBUG
+Uint32 _mdvi_debug_mask = 0;
+
+void __debug(int mask, const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ if(_mdvi_debug_mask & mask) {
+ if(!DEBUGGING(SILENT)) {
+ fprintf(stderr, "Debug: ");
+ vfprintf(stderr, format, ap);
+ fflush(stderr);
+ }
+#ifndef __GNUC__
+ /* let's be portable */
+ va_end(ap);
+ va_start(ap, format);
+#endif
+ vputlog(LOG_DEBUG, "Debug", format, ap);
+ }
+ va_end(ap);
+}
+#endif
+
+void mdvi_message(const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ if(_mdvi_log_level >= LOG_INFO) {
+ fprintf(stderr, "%s: ", program_name);
+ vfprintf(stderr, format, ap);
+#ifndef __GNUC__
+ va_end(ap);
+ va_start(ap, format);
+#endif
+ }
+ vputlog(LOG_INFO, NULL, format, ap);
+ va_end(ap);
+}
+
+void mdvi_crash(const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ fprintf(stderr, "%s: %s: ",
+ program_name,
+ gettext(messages[(int)time(NULL) % NMSGS]));
+ vfprintf(stderr, format, ap);
+#ifndef __GNUC__
+ /* let's be portable */
+ va_end(ap);
+ va_start(ap, format);
+#endif
+ vputlog(LOG_ERROR, _("Crashing"), format, ap);
+ va_end(ap);
+ abort();
+}
+
+void mdvi_error(const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ fprintf(stderr, _("%s: Error: "), program_name);
+ vfprintf(stderr, format, ap);
+#ifndef __GNUC__
+ /* let's be portable */
+ va_end(ap);
+ va_start(ap, format);
+#endif
+ vputlog(LOG_ERROR, _("Error"), format, ap);
+ va_end(ap);
+}
+
+void mdvi_warning(const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ fprintf(stderr, _("%s: Warning: "), program_name);
+ vfprintf(stderr, format, ap);
+#ifndef __GNUC__
+ /* let's be portable */
+ va_end(ap);
+ va_start(ap, format);
+#endif
+ vputlog(LOG_WARN, _("Warning"), format, ap);
+ va_end(ap);
+}
+
+void mdvi_fatal(const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ fprintf(stderr, _("%s: Fatal: "), program_name);
+ vfprintf(stderr, format, ap);
+#ifndef __GNUC__
+ /* let's be portable */
+ va_end(ap);
+ va_start(ap, format);
+#endif
+ vputlog(LOG_ERROR, _("Fatal"), format, ap);
+ va_end(ap);
+#ifndef NODEBUG
+ abort();
+#else
+ exit(EXIT_FAILURE);
+#endif
+}
+
+void *mdvi_malloc(size_t nelems)
+{
+ void *ptr = malloc(nelems);
+
+ if(ptr == NULL)
+ mdvi_fatal(_("out of memory allocating %u bytes\n"),
+ (unsigned)nelems);
+ return ptr;
+}
+
+void *mdvi_realloc(void *data, size_t newsize)
+{
+ void *ptr;
+
+ if(newsize == 0)
+ mdvi_crash(_("attempted to reallocate with zero size\n"));
+ ptr = realloc(data, newsize);
+ if(ptr == NULL)
+ mdvi_fatal(_("failed to reallocate %u bytes\n"), (unsigned)newsize);
+ return ptr;
+}
+
+void *mdvi_calloc(size_t nmemb, size_t size)
+{
+ void *ptr;
+
+ if(nmemb == 0)
+ mdvi_crash(_("attempted to callocate 0 members\n"));
+ if(size == 0)
+ mdvi_crash(_("attempted to callocate %u members with size 0\n"),
+ (unsigned)nmemb);
+ ptr = calloc(nmemb, size);
+ if(ptr == 0)
+ mdvi_fatal(_("failed to allocate %ux%u bytes\n"),
+ (unsigned)nmemb, (unsigned)size);
+ return ptr;
+}
+
+void mdvi_free(void *ptr)
+{
+ if(ptr == NULL)
+ mdvi_crash(_("attempted to free NULL pointer\n"));
+ free(ptr);
+}
+
+char *mdvi_strdup(const char *string)
+{
+ int length;
+ char *ptr;
+
+ length = strlen(string) + 1;
+ ptr = (char *)mdvi_malloc(length);
+ memcpy(ptr, string, length);
+ return ptr;
+}
+
+/* `to' should have room for length+1 bytes */
+char *mdvi_strncpy(char *to, const char *from, size_t length)
+{
+ strncpy(to, from, length);
+ to[length] = '\0';
+ return to;
+}
+
+char *mdvi_strndup(const char *string, size_t length)
+{
+ int n;
+ char *ptr;
+
+ n = strlen(string);
+ if(n > length)
+ n = length;
+ ptr = (char *)mdvi_malloc(n + 1);
+ memcpy(ptr, string, n);
+ return ptr;
+}
+
+void *mdvi_memdup(const void *data, size_t length)
+{
+ void *ptr = mdvi_malloc(length);
+
+ memcpy(ptr, data, length);
+ return ptr;
+}
+
+char *mdvi_strrstr (const char *haystack, const char *needle)
+{
+ size_t i;
+ size_t needle_len;
+ size_t haystack_len;
+ const char *p;
+
+ needle_len = strlen (needle);
+ haystack_len = strlen (haystack);
+
+ if (needle_len == 0)
+ return NULL;
+
+ if (haystack_len < needle_len)
+ return (char *)haystack;
+
+ p = haystack + haystack_len - needle_len;
+ while (p >= haystack) {
+ for (i = 0; i < needle_len; i++)
+ if (p[i] != needle[i])
+ goto next;
+
+ return (char *)p;
+
+ next:
+ p--;
+ }
+
+ return NULL;
+}
+
+char *mdvi_build_path_from_cwd (const char *path)
+{
+ char *ptr;
+ char *buf = NULL;
+ size_t buf_size = 512;
+
+ while (1) {
+ buf = mdvi_realloc (buf, buf_size);
+ if ((ptr = getcwd (buf, buf_size)) == NULL && errno == ERANGE) {
+ buf_size *= 2;
+ } else {
+ buf = ptr;
+ break;
+ }
+ }
+
+ buf = mdvi_realloc (buf, strlen (buf) + strlen (path) + 2);
+ strcat (buf, "/");
+ strncat (buf, path, strlen (path));
+
+ return buf;
+}
+
+double unit2pix_factor(const char *spec)
+{
+ double val;
+ double factor;
+ const char *p, *q;
+ static const char *units = "incmmmmtptpcddccspbpftydcs";
+
+ val = 0.0;
+
+ for(p = spec; *p >= '0' && *p <= '9'; p++)
+ val = 10.0 * val + (double)(*p - '0');
+ if(*p == '.') {
+ p++;
+ factor = 0.1;
+ while(*p && *p >= '0' && *p <= '9') {
+ val += (*p++ - '0') * factor;
+ factor = factor * 0.1;
+ }
+ }
+ factor = 1.0;
+ for(q = units; *q; q += 2) {
+ if(p[0] == q[0] && p[1] == q[1])
+ break;
+ }
+ switch((int)(q - units)) {
+ /*in*/ case 0: factor = 1.0; break;
+ /*cm*/ case 2: factor = 1.0 / 2.54; break;
+ /*mm*/ case 4: factor = 1.0 / 25.4; break;
+ /*mt*/ case 6: factor = 1.0 / 0.0254; break;
+ /*pt*/ case 8: factor = 1.0 / 72.27; break;
+ /*pc*/ case 10: factor = 12.0 / 72.27; break;
+ /*dd*/ case 12: factor = (1238.0 / 1157.0) / 72.27; break;
+ /*cc*/ case 14: factor = 12 * (1238.0 / 1157.0) / 72.27; break;
+ /*sp*/ case 16: factor = 1.0 / (72.27 * 65536); break;
+ /*bp*/ case 18: factor = 1.0 / 72.0; break;
+ /*ft*/ case 20: factor = 12.0; break;
+ /*yd*/ case 22: factor = 36.0; break;
+ /*cs*/ case 24: factor = 1.0 / 72000.0; break;
+ default: factor = 1.0;
+ }
+ return factor * val;
+}
+
+int unit2pix(int dpi, const char *spec)
+{
+ double factor = unit2pix_factor(spec);
+
+ return (int)(factor * dpi + 0.5);
+}
+
+Ulong get_mtime(int fd)
+{
+ struct stat st;
+
+ if(fstat(fd, &st) == 0)
+ return (Ulong)st.st_mtime;
+ return 0;
+}
+
+char *xstradd(char *dest, size_t *size, size_t n, const char *src, size_t m)
+{
+ if(m == 0)
+ m = strlen(src);
+ if(n + m >= *size) {
+ dest = mdvi_realloc(dest, n + m + 1);
+ *size = n + m + 1;
+ }
+ memcpy(dest + n, src, m);
+ dest[n + m] = 0;
+ return dest;
+}
+
+char *getword(char *string, const char *delim, char **end)
+{
+ char *ptr;
+ char *word;
+
+ /* skip leading delimiters */
+ for(ptr = string; *ptr && strchr(delim, *ptr); ptr++);
+
+ if(*ptr == 0)
+ return NULL;
+ word = ptr++;
+ /* skip non-delimiters */
+ while(*ptr && !strchr(delim, *ptr))
+ ptr++;
+ *end = (char *)ptr;
+ return word;
+}
+
+char *getstring(char *string, const char *delim, char **end)
+{
+ char *ptr;
+ char *word;
+ int quoted = 0;
+
+ /* skip leading delimiters */
+ for(ptr = string; *ptr && strchr(delim, *ptr); ptr++);
+
+ if(ptr == NULL)
+ return NULL;
+ quoted = (*ptr == '"');
+ if(quoted)
+ for(word = ++ptr; *ptr && *ptr != '"'; ptr++);
+ else
+ for(word = ptr; *ptr && !strchr(delim, *ptr); ptr++);
+ *end = (char *)ptr;
+ return word;
+}
+
+static long pow2(size_t n)
+{
+ long x = 8; /* don't bother allocating less than this */
+
+ while(x < n)
+ x <<= 1L;
+ return x;
+}
+
+void dstring_init(Dstring *dstr)
+{
+ dstr->data = NULL;
+ dstr->size = 0;
+ dstr->length = 0;
+}
+
+int dstring_append(Dstring *dstr, const char *string, int len)
+{
+ if(len < 0)
+ len = strlen(string);
+ if(len) {
+ if(dstr->length + len >= dstr->size) {
+ dstr->size = pow2(dstr->length + len + 1);
+ dstr->data = mdvi_realloc(dstr->data, dstr->size);
+ }
+ memcpy(dstr->data + dstr->length, string, len);
+ dstr->length += len;
+ dstr->data[dstr->length] = 0;
+ } else if(dstr->size == 0) {
+ ASSERT(dstr->data == NULL);
+ dstr->size = 8;
+ dstr->data = mdvi_malloc(8);
+ dstr->data[0] = 0;
+ }
+
+ return dstr->length;
+}
+
+int dstring_copy(Dstring *dstr, int pos, const char *string, int len)
+{
+ ASSERT(pos >= 0);
+ if(len < 0)
+ len = strlen(string);
+ if(len) {
+ if(pos + len >= dstr->length) {
+ dstr->length = pos;
+ return dstring_append(dstr, string, len);
+ }
+ memcpy(dstr->data + pos, string, len);
+ }
+ return dstr->length;
+}
+
+int dstring_insert(Dstring *dstr, int pos, const char *string, int len)
+{
+ ASSERT(pos >= 0);
+ if(pos == dstr->length)
+ return dstring_append(dstr, string, len);
+ if(len < 0)
+ len = strlen(string);
+ if(len) {
+ if(dstr->length + len >= dstr->size) {
+ dstr->size = pow2(dstr->length + len + 1);
+ dstr->data = mdvi_realloc(dstr->data, dstr->size);
+ }
+ /* make room */
+ memmove(dstr->data + pos, dstr->data + pos + len, len);
+ /* now copy */
+ memcpy(dstr->data + pos, string, len);
+ dstr->length += len;
+ dstr->data[dstr->length] = 0;
+ }
+ return dstr->length;
+}
+
+int dstring_new(Dstring *dstr, const char *string, int len)
+{
+ if(len < 0)
+ len = strlen(string);
+ if(len) {
+ dstr->size = pow2(len + 1);
+ dstr->data = mdvi_malloc(dstr->size * len);
+ memcpy(dstr->data, string, len);
+ } else
+ dstring_init(dstr);
+ return dstr->length;
+}
+
+void dstring_reset(Dstring *dstr)
+{
+ if(dstr->data)
+ mdvi_free(dstr->data);
+ dstring_init(dstr);
+}
+