More honesty about bug 144394, it's not quite fixed yet.
[dia.git] / lib / utils.c
blobf5172968ef926fdee7f032b91a85605230eac566
1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
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.
19 /* This file contains some code from glib.
20 Here is the copyright notice:
22 * GLIB - Library of useful routines for C programming
23 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
27 #include <config.h>
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <string.h>
33 #include <glib.h>
35 #include "utils.h"
37 int
38 nearest_pow (int num)
40 int n = 1;
42 while (n < num)
43 n <<= 1;
45 return n;
48 int
49 format_string_length_upper_bound (const char* fmt, va_list *args)
50 { /* UTF8 ? */
51 int len = 0;
52 int short_int;
53 int long_int;
54 int done;
55 char *tmp;
57 while (*fmt)
59 char c = *fmt++;
61 short_int = FALSE;
62 long_int = FALSE;
64 if (c == '%')
66 done = FALSE;
67 while (*fmt && !done)
69 switch (*fmt++)
71 case '*':
72 len += va_arg(*args, int);
73 break;
74 case '1':
75 case '2':
76 case '3':
77 case '4':
78 case '5':
79 case '6':
80 case '7':
81 case '8':
82 case '9':
83 fmt -= 1;
84 len += strtol (fmt, (char **)&fmt, 10);
85 break;
86 case 'h':
87 short_int = TRUE;
88 break;
89 case 'l':
90 long_int = TRUE;
91 break;
93 /* I ignore 'q' and 'L', they're not portable anyway. */
95 case 's':
96 tmp = va_arg(*args, char *);
97 if(tmp)
98 len += strlen (tmp);
99 else
100 len += strlen ("(null)");
101 done = TRUE;
102 break;
103 case 'd':
104 case 'i':
105 case 'o':
106 case 'u':
107 case 'x':
108 case 'X':
109 if (long_int)
110 (void)va_arg (*args, long);
111 else if (short_int)
112 (void)va_arg (*args, int);
113 else
114 (void)va_arg (*args, int);
115 len += 32;
116 done = TRUE;
117 break;
118 case 'D':
119 case 'O':
120 case 'U':
121 (void)va_arg (*args, long);
122 len += 32;
123 done = TRUE;
124 break;
125 case 'e':
126 case 'E':
127 case 'f':
128 case 'g':
129 (void)va_arg (*args, double);
130 len += 32;
131 done = TRUE;
132 break;
133 case 'c':
134 (void)va_arg (*args, int);
135 len += 1;
136 done = TRUE;
137 break;
138 case 'p':
139 case 'n':
140 (void)va_arg (*args, void*);
141 len += 32;
142 done = TRUE;
143 break;
144 case '%':
145 len += 1;
146 done = TRUE;
147 break;
148 default:
149 break;
153 else
154 len += 1;
157 return len;
160 #ifndef HAVE_SNPRINTF
162 snprintf ( char *str, size_t n, const char *format, ... )
164 static char *buf = NULL;
165 static int alloc = 0;
166 int len;
167 va_list args, args2;
169 va_start (args, format);
170 len = format_string_length_upper_bound (format, &args);
171 va_end (args);
173 if (len >= alloc) {
174 if (buf)
175 g_free (buf);
177 alloc = nearest_pow (MAX(len + 1, 1024));
179 buf = g_new (char, alloc);
182 va_start (args2, format);
183 vsprintf (buf, format, args2);
184 va_end (args2);
186 strncpy(str, buf, n);
187 str[n-1] = 0;
189 return (len >= n)?-1:strlen(str);
191 #endif