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