]> www.fi.muni.cz Git - evince.git/blob - backend/dvi/mdvi-lib/util.c
0fe66cd97e617f08bdbdee2e5e33723d3cde294f
[evince.git] / backend / dvi / mdvi-lib / util.c
1 /*
2  * Copyright (C) 2000, Matias Atria
3  *
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.
8  *
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.
13  *
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
17  */
18
19 #include <config.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <stdarg.h>
23 #include <string.h>
24 #include <time.h>
25 #include <sys/stat.h>
26 #include <errno.h>
27 #include <unistd.h>
28
29 #include "common.h"
30 #include "private.h"
31
32 static char *const messages[] = {
33         _G("Ooops!"),
34         _G("Aieeeee!!"),
35         _G("Ouch!"),
36         _G("Houston, we have a problem"),
37         _G("3.. 2.. 1.. BOOM!"),
38         _G("I'm history"),
39         _G("I'm going down"),
40         _G("I smell a rat")
41 };
42 #define NMSGS   (sizeof(messages) / sizeof(char *))
43
44 static FILE *logfile = NULL;
45 static int _mdvi_log_level;
46
47 int mdvi_set_logfile(const char *filename);
48 int mdvi_set_logstream(FILE *file);
49 int mdvi_set_loglevel(int level);
50
51 static void vputlog(int level, const char *head, const char *format, va_list ap)
52 {
53         if(logfile != NULL && _mdvi_log_level >= level) {
54                 if(head != NULL)
55                         fprintf(logfile, "%s: ", head);
56                 vfprintf(logfile, format, ap);
57         }
58 }
59
60 int mdvi_set_logfile(const char *filename)
61 {
62         FILE    *f = NULL;
63
64         if(filename && (f = fopen(filename, "w")) == NULL)
65                 return -1;
66         if(logfile != NULL && !isatty(fileno(logfile))) {
67                 fclose(logfile);
68                 logfile = NULL;
69         }
70         if(filename)
71                 logfile = f;
72         return 0;
73 }
74
75 int mdvi_set_logstream(FILE *file)
76 {
77         if(logfile && !isatty(fileno(logfile))) {
78                 fclose(logfile);
79                 logfile = NULL;
80         }
81         logfile = file;
82         return 0;
83 }
84
85 int mdvi_set_loglevel(int level)
86 {
87         int     old = _mdvi_log_level;
88         
89         _mdvi_log_level = level;
90         return old;
91 }
92
93 #ifndef NODEBUG
94 Uint32 _mdvi_debug_mask = 0;
95
96 void    __debug(int mask, const char *format, ...)
97 {
98         va_list ap;
99         
100         va_start(ap, format);
101         if(_mdvi_debug_mask & mask) {
102                 if(!DEBUGGING(SILENT)) {
103                         fprintf(stderr, "Debug: ");
104                         vfprintf(stderr, format, ap);
105                         fflush(stderr);
106                 }
107 #ifndef __GNUC__
108                 /* let's be portable */
109                 va_end(ap);
110                 va_start(ap, format);
111 #endif
112                 vputlog(LOG_DEBUG, "Debug", format, ap);
113         }
114         va_end(ap);
115 }
116 #endif
117
118 void    mdvi_message(const char *format, ...)
119 {
120         va_list ap;
121         
122         va_start(ap, format);
123         if(_mdvi_log_level >= LOG_INFO) {
124                 fprintf(stderr, "%s: ", program_name);
125                 vfprintf(stderr, format, ap);
126 #ifndef __GNUC__
127                 va_end(ap);
128                 va_start(ap, format);
129 #endif
130         }
131         vputlog(LOG_INFO, NULL, format, ap);
132         va_end(ap);
133 }
134
135 void    mdvi_crash(const char *format, ...)
136 {
137         va_list ap;
138         
139         va_start(ap, format);
140         fprintf(stderr, "%s: %s: ", 
141                 program_name, 
142                 gettext(messages[(int)time(NULL) % NMSGS]));
143         vfprintf(stderr, format, ap);
144 #ifndef __GNUC__
145         /* let's be portable */
146         va_end(ap);
147         va_start(ap, format);
148 #endif
149         vputlog(LOG_ERROR, _("Crashing"), format, ap);
150         va_end(ap);
151         abort();
152 }
153
154 void    mdvi_error(const char *format, ...)
155 {
156         va_list ap;
157         
158         va_start(ap, format);
159         fprintf(stderr, _("%s: Error: "), program_name);
160         vfprintf(stderr, format, ap);
161 #ifndef __GNUC__
162         /* let's be portable */
163         va_end(ap);
164         va_start(ap, format);
165 #endif
166         vputlog(LOG_ERROR, _("Error"), format, ap);
167         va_end(ap);
168 }
169
170 void    mdvi_warning(const char *format, ...)
171 {
172         va_list ap;
173         
174         va_start(ap, format);
175         fprintf(stderr, _("%s: Warning: "), program_name);
176         vfprintf(stderr, format, ap);
177 #ifndef __GNUC__
178         /* let's be portable */
179         va_end(ap);
180         va_start(ap, format);
181 #endif
182         vputlog(LOG_WARN, _("Warning"), format, ap);
183         va_end(ap);
184 }
185
186 void    mdvi_fatal(const char *format, ...)
187 {
188         va_list ap;
189         
190         va_start(ap, format);
191         fprintf(stderr, _("%s: Fatal: "), program_name);
192         vfprintf(stderr, format, ap);
193 #ifndef __GNUC__
194         /* let's be portable */
195         va_end(ap);
196         va_start(ap, format);
197 #endif
198         vputlog(LOG_ERROR, _("Fatal"), format, ap);
199         va_end(ap);
200 #ifndef NODEBUG
201         abort();
202 #else
203         exit(EXIT_FAILURE);
204 #endif
205 }
206
207 void    *mdvi_malloc(size_t nelems)
208 {
209         void    *ptr = malloc(nelems);
210         
211         if(ptr == NULL)
212                 mdvi_fatal(_("out of memory allocating %u bytes\n"),
213                            (unsigned)nelems);
214         return ptr;
215 }
216
217 void    *mdvi_realloc(void *data, size_t newsize)
218 {
219         void    *ptr;
220         
221         if(newsize == 0)
222                 mdvi_crash(_("attempted to reallocate with zero size\n"));
223         ptr = realloc(data, newsize);
224         if(ptr == NULL)
225                 mdvi_fatal(_("failed to reallocate %u bytes\n"), (unsigned)newsize);
226         return ptr;     
227 }
228
229 void    *mdvi_calloc(size_t nmemb, size_t size)
230 {
231         void    *ptr;
232         
233         if(nmemb == 0)
234                 mdvi_crash(_("attempted to callocate 0 members\n"));
235         if(size == 0)
236                 mdvi_crash(_("attempted to callocate %u members with size 0\n"),
237                         (unsigned)nmemb);
238         ptr = calloc(nmemb, size);
239         if(ptr == 0)
240                 mdvi_fatal(_("failed to allocate %ux%u bytes\n"),
241                            (unsigned)nmemb, (unsigned)size);
242         return ptr;
243 }
244
245 void    mdvi_free(void *ptr)
246 {
247         if(ptr == NULL)
248                 mdvi_crash(_("attempted to free NULL pointer\n"));
249         free(ptr);
250 }
251
252 char    *mdvi_strdup(const char *string)
253 {
254         int     length;
255         char    *ptr;
256         
257         length = strlen(string) + 1;
258         ptr = (char *)mdvi_malloc(length);
259         memcpy(ptr, string, length);
260         return ptr;
261 }
262
263 /* `to' should have room for length+1 bytes */
264 char    *mdvi_strncpy(char *to, const char *from, size_t length)
265 {
266         strncpy(to, from, length);
267         to[length] = '\0';
268         return to;
269 }
270
271 char    *mdvi_strndup(const char *string, size_t length)
272 {
273         int     n;
274         char    *ptr;
275         
276         n = strlen(string);
277         if(n > length)
278                 n = length;
279         ptr = (char *)mdvi_malloc(n + 1);
280         memcpy(ptr, string, n);
281         return ptr;
282 }
283
284 void    *mdvi_memdup(const void *data, size_t length)
285 {
286         void    *ptr = mdvi_malloc(length);
287         
288         memcpy(ptr, data, length);
289         return ptr;
290 }
291
292 char   *mdvi_strrstr (const char *haystack, const char *needle)
293 {
294         size_t i;
295         size_t needle_len;
296         size_t haystack_len;
297         const char *p;
298
299         needle_len = strlen (needle);
300         haystack_len = strlen (haystack);
301
302         if (needle_len == 0)
303                 return NULL;
304
305         if (haystack_len < needle_len)
306                 return (char *)haystack;
307
308         p = haystack + haystack_len - needle_len;
309         while (p >= haystack) {
310                 for (i = 0; i < needle_len; i++)
311                         if (p[i] != needle[i])
312                                 goto next;
313
314                 return (char *)p;
315
316         next:
317                 p--;
318         }
319
320         return NULL;
321 }
322
323 char   *mdvi_build_path_from_cwd (const char *path)
324 {
325         char  *ptr;
326         char  *buf = NULL;
327         size_t buf_size = 512;
328
329         while (1) {
330                 buf = mdvi_realloc (buf, buf_size);
331                 if ((ptr = getcwd (buf, buf_size)) == NULL && errno == ERANGE) {
332                         buf_size *= 2;
333                 } else {
334                         buf = ptr;
335                         break;
336                 }
337         }
338
339         buf = mdvi_realloc (buf, strlen (buf) + strlen (path) + 2);
340         strcat (buf, "/");
341         strncat (buf, path, strlen (path));
342         
343         return buf;
344 }
345
346 double  unit2pix_factor(const char *spec)
347 {
348         double  val;
349         double  factor;
350         const char *p, *q;
351         static const char *units = "incmmmmtptpcddccspbpftydcs";
352         
353         val = 0.0;
354         
355         for(p = spec; *p >= '0' && *p <= '9'; p++)
356                 val = 10.0 * val + (double)(*p - '0');
357         if(*p == '.') {
358                 p++;
359                 factor = 0.1;
360                 while(*p && *p >= '0' && *p <= '9') {
361                         val += (*p++ - '0') * factor;
362                         factor = factor * 0.1;
363                 }
364         }
365         factor = 1.0;
366         for(q = units; *q; q += 2) {
367                 if(p[0] == q[0] && p[1] == q[1])
368                         break;
369         }
370         switch((int)(q - units)) {
371         /*in*/  case 0:  factor = 1.0; break;
372         /*cm*/  case 2:  factor = 1.0 / 2.54; break;
373         /*mm*/  case 4:  factor = 1.0 / 25.4; break;
374         /*mt*/  case 6:  factor = 1.0 / 0.0254; break;
375         /*pt*/  case 8:  factor = 1.0 / 72.27; break;
376         /*pc*/  case 10: factor = 12.0 / 72.27; break;
377         /*dd*/  case 12: factor = (1238.0 / 1157.0) / 72.27; break;
378         /*cc*/  case 14: factor = 12 * (1238.0 / 1157.0) / 72.27; break;
379         /*sp*/  case 16: factor = 1.0 / (72.27 * 65536); break;
380         /*bp*/  case 18: factor = 1.0 / 72.0; break;
381         /*ft*/  case 20: factor = 12.0; break;
382         /*yd*/  case 22: factor = 36.0; break;
383         /*cs*/  case 24: factor = 1.0 / 72000.0; break;
384                 default: factor = 1.0;
385         }
386         return factor * val;
387 }
388
389 int     unit2pix(int dpi, const char *spec)
390 {
391         double  factor = unit2pix_factor(spec);
392         
393         return (int)(factor * dpi + 0.5);
394 }
395
396 Ulong   get_mtime(int fd)
397 {
398         struct stat st;
399         
400         if(fstat(fd, &st) == 0)
401                 return (Ulong)st.st_mtime;
402         return 0;
403 }
404
405 char    *xstradd(char *dest, size_t *size, size_t n, const char *src, size_t m)
406 {
407         if(m == 0)
408                 m = strlen(src);
409         if(n + m >= *size) {
410                 dest = mdvi_realloc(dest, n + m + 1);
411                 *size = n + m + 1;
412         }
413         memcpy(dest + n, src, m);
414         dest[n + m] = 0;
415         return dest;
416 }
417
418 char    *getword(char *string, const char *delim, char **end)
419 {
420         char *ptr;
421         char *word;
422         
423         /* skip leading delimiters */
424         for(ptr = string; *ptr && strchr(delim, *ptr); ptr++);
425
426         if(*ptr == 0)
427                 return NULL;
428         word = ptr++;
429         /* skip non-delimiters */
430         while(*ptr && !strchr(delim, *ptr))
431                 ptr++;
432         *end = (char *)ptr;
433         return word;
434 }
435
436 char    *getstring(char *string, const char *delim, char **end)
437 {
438         char *ptr;
439         char *word;
440         int     quoted = 0;
441         
442         /* skip leading delimiters */
443         for(ptr = string; *ptr && strchr(delim, *ptr); ptr++);
444         
445         if(ptr == NULL)
446                 return NULL;
447         quoted = (*ptr == '"');
448         if(quoted)
449                 for(word = ++ptr; *ptr && *ptr != '"'; ptr++);
450         else
451                 for(word = ptr; *ptr && !strchr(delim, *ptr); ptr++);
452         *end = (char *)ptr;
453         return word;
454 }
455
456 static long pow2(size_t n)
457 {
458         long    x = 8; /* don't bother allocating less than this */
459         
460         while(x < n)
461                 x <<= 1L;
462         return x;
463 }
464
465 void    dstring_init(Dstring *dstr)
466 {
467         dstr->data = NULL;
468         dstr->size = 0;
469         dstr->length = 0;
470 }
471
472 int     dstring_append(Dstring *dstr, const char *string, int len)
473 {
474         if(len < 0)
475                 len = strlen(string);
476         if(len) {
477                 if(dstr->length + len >= dstr->size) {
478                         dstr->size = pow2(dstr->length + len + 1);
479                         dstr->data = mdvi_realloc(dstr->data, dstr->size);
480                 }
481                 memcpy(dstr->data + dstr->length, string, len);
482                 dstr->length += len;
483                 dstr->data[dstr->length] = 0;
484         } else if(dstr->size == 0) {
485                 ASSERT(dstr->data == NULL);
486                 dstr->size = 8;
487                 dstr->data = mdvi_malloc(8);
488                 dstr->data[0] = 0;
489         }
490                 
491         return dstr->length;
492 }
493
494 int     dstring_copy(Dstring *dstr, int pos, const char *string, int len)
495 {
496         ASSERT(pos >= 0);
497         if(len < 0)
498                 len = strlen(string);
499         if(len) {
500                 if(pos + len >= dstr->length) {
501                         dstr->length = pos;
502                         return dstring_append(dstr, string, len);
503                 }
504                 memcpy(dstr->data + pos, string, len);
505         }
506         return dstr->length;
507 }
508
509 int     dstring_insert(Dstring *dstr, int pos, const char *string, int len)
510 {
511         ASSERT(pos >= 0);
512         if(pos == dstr->length)
513                 return dstring_append(dstr, string, len);
514         if(len < 0)
515                 len = strlen(string);
516         if(len) {
517                 if(dstr->length + len >= dstr->size) {
518                         dstr->size = pow2(dstr->length + len + 1);
519                         dstr->data = mdvi_realloc(dstr->data, dstr->size);
520                 }
521                 /* make room */
522                 memmove(dstr->data + pos, dstr->data + pos + len, len);
523                 /* now copy */
524                 memcpy(dstr->data + pos, string, len);
525                 dstr->length += len;
526                 dstr->data[dstr->length] = 0;
527         }
528         return dstr->length;
529 }
530
531 int     dstring_new(Dstring *dstr, const char *string, int len)
532 {
533         if(len < 0)
534                 len = strlen(string);
535         if(len) {
536                 dstr->size = pow2(len + 1);
537                 dstr->data = mdvi_malloc(dstr->size * len);
538                 memcpy(dstr->data, string, len);
539         } else
540                 dstring_init(dstr);
541         return dstr->length;
542 }
543
544 void    dstring_reset(Dstring *dstr)
545 {
546         if(dstr->data)
547                 mdvi_free(dstr->data);
548         dstring_init(dstr);
549 }
550