2 * Copyright (C) 2000, Matias Atria
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 static char *const messages[] = {
35 _G("Houston, we have a problem"),
36 _G("3.. 2.. 1.. BOOM!"),
41 #define NMSGS (sizeof(messages) / sizeof(char *))
43 static FILE *logfile = NULL;
44 static int _mdvi_log_level;
46 int mdvi_set_logfile(const char *filename);
47 int mdvi_set_logstream(FILE *file);
48 int mdvi_set_loglevel(int level);
50 static void vputlog(int level, const char *head, const char *format, va_list ap)
52 if(logfile != NULL && _mdvi_log_level >= level) {
54 fprintf(logfile, "%s: ", head);
55 vfprintf(logfile, format, ap);
59 int mdvi_set_logfile(const char *filename)
63 if(filename && (f = fopen(filename, "w")) == NULL)
65 if(logfile != NULL && !isatty(fileno(logfile))) {
74 int mdvi_set_logstream(FILE *file)
76 if(logfile && !isatty(fileno(logfile))) {
84 int mdvi_set_loglevel(int level)
86 int old = _mdvi_log_level;
88 _mdvi_log_level = level;
93 Uint32 _mdvi_debug_mask = 0;
95 void __debug(int mask, const char *format, ...)
100 if(_mdvi_debug_mask & mask) {
101 if(!DEBUGGING(SILENT)) {
102 fprintf(stderr, "Debug: ");
103 vfprintf(stderr, format, ap);
107 /* let's be portable */
109 va_start(ap, format);
111 vputlog(LOG_DEBUG, "Debug", format, ap);
117 void message(const char *format, ...)
121 va_start(ap, format);
122 if(_mdvi_log_level >= LOG_INFO) {
123 fprintf(stderr, "%s: ", program_name);
124 vfprintf(stderr, format, ap);
127 va_start(ap, format);
130 vputlog(LOG_INFO, NULL, format, ap);
134 void crash(const char *format, ...)
138 va_start(ap, format);
139 fprintf(stderr, "%s: %s: ",
141 gettext(messages[(int)time(NULL) % NMSGS]));
142 vfprintf(stderr, format, ap);
144 /* let's be portable */
146 va_start(ap, format);
148 vputlog(LOG_ERROR, _("Crashing"), format, ap);
153 void error(const char *format, ...)
157 va_start(ap, format);
158 fprintf(stderr, _("%s: Error: "), program_name);
159 vfprintf(stderr, format, ap);
161 /* let's be portable */
163 va_start(ap, format);
165 vputlog(LOG_ERROR, _("Error"), format, ap);
169 void warning(const char *format, ...)
173 va_start(ap, format);
174 fprintf(stderr, _("%s: Warning: "), program_name);
175 vfprintf(stderr, format, ap);
177 /* let's be portable */
179 va_start(ap, format);
181 vputlog(LOG_WARN, _("Warning"), format, ap);
185 void fatal(const char *format, ...)
189 va_start(ap, format);
190 fprintf(stderr, _("%s: Fatal: "), program_name);
191 vfprintf(stderr, format, ap);
193 /* let's be portable */
195 va_start(ap, format);
197 vputlog(LOG_ERROR, _("Fatal"), format, ap);
206 void *xmalloc(size_t nelems)
208 void *ptr = malloc(nelems);
211 fatal(_("out of memory allocating %u bytes\n"),
216 void *xrealloc(void *data, size_t newsize)
221 crash(_("attempted to reallocate with zero size\n"));
222 ptr = realloc(data, newsize);
224 fatal(_("failed to reallocate %u bytes\n"), (unsigned)newsize);
228 void *xcalloc(size_t nmemb, size_t size)
233 crash(_("attempted to callocate 0 members\n"));
235 crash(_("attempted to callocate %u members with size 0\n"),
237 ptr = calloc(nmemb, size);
239 fatal(_("failed to allocate %ux%u bytes\n"),
240 (unsigned)nmemb, (unsigned)size);
244 void xfree(void *ptr)
247 crash(_("attempted to free NULL pointer\n"));
251 char *xstrdup(const char *string)
256 length = strlen(string) + 1;
257 ptr = (char *)xmalloc(length);
258 memcpy(ptr, string, length);
262 /* `to' should have room for length+1 bytes */
263 char *xstrncpy(char *to, const char *from, size_t length)
265 strncpy(to, from, length);
270 char *xstrndup(const char *string, size_t length)
278 ptr = (char *)xmalloc(n + 1);
279 memcpy(ptr, string, n);
283 void *xmemdup(const void *data, size_t length)
285 void *ptr = xmalloc(length);
287 memcpy(ptr, data, length);
291 double unit2pix_factor(const char *spec)
296 static const char *units = "incmmmmtptpcddccspbpftydcs";
300 for(p = spec; *p >= '0' && *p <= '9'; p++)
301 val = 10.0 * val + (double)(*p - '0');
305 while(*p && *p >= '0' && *p <= '9') {
306 val += (*p++ - '0') * factor;
307 factor = factor * 0.1;
311 for(q = units; *q; q += 2) {
312 if(p[0] == q[0] && p[1] == q[1])
315 switch((int)(q - units)) {
316 /*in*/ case 0: factor = 1.0; break;
317 /*cm*/ case 2: factor = 1.0 / 2.54; break;
318 /*mm*/ case 4: factor = 1.0 / 25.4; break;
319 /*mt*/ case 6: factor = 1.0 / 0.0254; break;
320 /*pt*/ case 8: factor = 1.0 / 72.27; break;
321 /*pc*/ case 10: factor = 12.0 / 72.27; break;
322 /*dd*/ case 12: factor = (1238.0 / 1157.0) / 72.27; break;
323 /*cc*/ case 14: factor = 12 * (1238.0 / 1157.0) / 72.27; break;
324 /*sp*/ case 16: factor = 1.0 / (72.27 * 65536); break;
325 /*bp*/ case 18: factor = 1.0 / 72.0; break;
326 /*ft*/ case 20: factor = 12.0; break;
327 /*yd*/ case 22: factor = 36.0; break;
328 /*cs*/ case 24: factor = 1.0 / 72000.0; break;
329 default: factor = 1.0;
334 int unit2pix(int dpi, const char *spec)
336 double factor = unit2pix_factor(spec);
338 return (int)(factor * dpi + 0.5);
341 Ulong get_mtime(int fd)
345 if(fstat(fd, &st) == 0)
346 return (Ulong)st.st_mtime;
350 char *xstradd(char *dest, size_t *size, size_t n, const char *src, size_t m)
355 dest = xrealloc(dest, n + m + 1);
358 memcpy(dest + n, src, m);
363 char *getword(char *string, const char *delim, char **end)
368 /* skip leading delimiters */
369 for(ptr = string; *ptr && strchr(delim, *ptr); ptr++);
374 /* skip non-delimiters */
375 while(*ptr && !strchr(delim, *ptr))
381 char *getstring(char *string, const char *delim, char **end)
387 /* skip leading delimiters */
388 for(ptr = string; *ptr && strchr(delim, *ptr); ptr++);
392 quoted = (*ptr == '"');
394 for(word = ++ptr; *ptr && *ptr != '"'; ptr++);
396 for(word = ptr; *ptr && !strchr(delim, *ptr); ptr++);
401 static long pow2(size_t n)
403 long x = 8; /* don't bother allocating less than this */
410 void dstring_init(Dstring *dstr)
417 int dstring_append(Dstring *dstr, const char *string, int len)
420 len = strlen(string);
422 if(dstr->length + len >= dstr->size) {
423 dstr->size = pow2(dstr->length + len + 1);
424 dstr->data = xrealloc(dstr->data, dstr->size);
426 memcpy(dstr->data + dstr->length, string, len);
428 dstr->data[dstr->length] = 0;
429 } else if(dstr->size == 0) {
430 ASSERT(dstr->data == NULL);
432 dstr->data = xmalloc(8);
439 int dstring_copy(Dstring *dstr, int pos, const char *string, int len)
443 len = strlen(string);
445 if(pos + len >= dstr->length) {
447 return dstring_append(dstr, string, len);
449 memcpy(dstr->data + pos, string, len);
454 int dstring_insert(Dstring *dstr, int pos, const char *string, int len)
457 if(pos == dstr->length)
458 return dstring_append(dstr, string, len);
460 len = strlen(string);
462 if(dstr->length + len >= dstr->size) {
463 dstr->size = pow2(dstr->length + len + 1);
464 dstr->data = xrealloc(dstr->data, dstr->size);
467 memmove(dstr->data + pos, dstr->data + pos + len, len);
469 memcpy(dstr->data + pos, string, len);
471 dstr->data[dstr->length] = 0;
476 int dstring_new(Dstring *dstr, const char *string, int len)
479 len = strlen(string);
481 dstr->size = pow2(len + 1);
482 dstr->data = xmalloc(dstr->size * len);
483 memcpy(dstr->data, string, len);
489 void dstring_reset(Dstring *dstr)