src/main.c: Make it possible to pass options to the app under test
[memprof.git] / lib / memintercept-utils.c
blob3cc540472550dc718bff285de8b4b471595cb0b2
1 #include <stdio.h>
2 /* -*- mode: C; c-file-style: "linux" -*- */
4 /* MemProf -- memory profiler and leak detector
5 * Copyright 1999, 2000, 2001, Red Hat, Inc.
6 * Copyright 2002, Kristian Rietveld
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 /*====*/
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <sys/socket.h> /* For send() */
27 #include <stdarg.h>
28 #include <string.h>
29 #include <sys/types.h>
30 #include <unistd.h>
32 #include "memintercept-utils.h"
34 static int
35 write_all (int fd,
36 const void *buf,
37 int total)
39 int count;
40 int written = 0;
42 while (written < total) {
43 /* Use send() to avoid EPIPE errors */
44 count = write (fd, buf + written, total - written);
45 if (count < 0) {
46 if (errno != EINTR)
47 return 0;
48 } else {
49 if (count == 0)
50 return 0;
51 written += count;
55 return 1;
58 static void
59 write_unsigned (int fd,
60 unsigned long num,
61 unsigned int radix)
63 char buffer[64];
64 unsigned long tmp;
65 char c;
66 int i, n;
68 if (!num) {
69 write_all (fd, "0", 1);
70 return;
73 if (radix == 16)
74 write_all (fd, "0x", 2);
75 else if (radix == 8)
76 write_all (fd, "0", 2);
78 n = 0;
79 tmp = num;
80 while (tmp) {
81 tmp /= radix;
82 n++;
85 i = n;
86 while (num) {
87 i--;
88 c = (num % radix);
89 if (c < 10)
90 buffer[i] = c + '0';
91 else
92 buffer[i] = c + 'a' - 10;
93 num /= radix;
96 write_all (fd, buffer, n);
100 static void
101 write_signed (int fd,
102 long num,
103 unsigned int radix)
105 if (num < 0) {
106 write_all (fd, "-", 1);
107 num = -num;
110 write_unsigned (fd, num, radix);
113 static void
114 mi_vprintf (int fd,
115 const char *format,
116 va_list va)
118 const char *p, *q;
119 int argi;
120 size_t argsize;
121 const void *argp;
122 const char *args = NULL;
123 long argl = 0;
125 p = q = format;
126 while ((p = strchr (p, '%'))) {
127 int is_size = 0;
129 write_all (fd, q, p - q);
130 q = p + 2;
132 again:
133 switch (*(p + 1)) {
134 case 'z':
135 is_size = 1;
136 q++;
137 p++;
138 goto again;
139 case 'd':
140 case 'u':
141 case 'x':
142 if (is_size) {
143 argsize = va_arg (va, size_t);
144 argl = argsize;
145 } else {
146 argi = va_arg (va, int);
147 argl = argi;
149 break;
150 case 'p':
151 argp = va_arg (va, void *);
152 argl = (long)argp;
153 break;
154 case 's':
155 args = va_arg (va, const char *);
156 break;
159 switch (*(p + 1)) {
160 case '%':
161 write_all (fd, "%", 1);
162 break;
163 case 'z':
164 is_size = 1;
165 q++;
166 p++;
167 goto again;
168 break;
169 case 'P':
170 write_signed (fd, getpid(), 10);
171 break;
172 case 'd':
173 write_signed (fd, argl, 10);
174 break;
175 case 'u':
176 write_unsigned (fd, argl, 10);
177 break;
178 case 'p':
179 case 'x':
180 write_unsigned (fd, argl, 16);
181 break;
182 case 's':
183 if (!args)
184 args = "(null)";
185 write_all (fd, args, strlen (args));
186 break;
187 case 0:
188 q--;
189 break;
191 p = q;
194 write_all (fd, q, strlen (q));
197 void
198 mi_printf (int fd,
199 const char *format,
200 ...)
202 va_list va;
204 va_start (va, format);
205 mi_vprintf (fd, format, va);
206 va_end (va);
209 void
210 mi_debug (const char *format,
211 ...)
213 static int fd = -1;
214 va_list va;
216 if (fd < 0) {
217 #if 0
218 fd = 2;
219 #else
220 fd = open ("/dev/tty", O_WRONLY);
221 #endif
225 mi_printf (fd, "memintercept (%P): ");
227 va_start (va, format);
228 mi_vprintf (fd, format, va);
229 va_end (va);
232 void
233 mi_perror (const char *message)
235 if (message && *message)
236 mi_debug ("%s: %s (%d)\n", message, strerror (errno), errno);
237 else
238 mi_debug ("%s (%d)\n", strerror (errno), errno);
242 mi_write (int fd,
243 const void *buf,
244 int total)
246 int count;
247 int written = 0;
249 while (written < total) {
250 /* Use send() to avoid EPIPE errors */
251 count = send (fd, buf + written, total - written, MSG_NOSIGNAL);
252 if (count < 0) {
253 if (errno != EINTR)
255 mi_debug ("mi_write error %d\n", errno);
256 return 0;
258 } else {
259 if (count == 0)
260 return 0;
261 written += count;
265 return 1;
268 uint32_t
269 mi_atomic_increment(uint32_t *addr)
271 #if defined (__GNUC__) && defined (__i386__)
272 uint32_t result;
273 __asm__ __volatile__("lock; xaddl %0, %1; incl %0"
274 : "=r"(result), "=m"(*(addr))
275 : "0" (1), "m"(*(addr)) : "memory");
276 return result;
277 #else
278 /* Hope for the best */
279 return *++addr;
280 #endif
283 uint32_t
284 mi_atomic_decrement(uint32_t *addr)
286 #if defined (__GNUC__) && defined (__i386__)
287 uint32_t result;
288 __asm__ __volatile__("lock; xaddl %0, %1; decl %0"
289 : "=r"(result), "=m"(*(addr))
290 : "0" (-1), "m"(*(addr)) : "memory");
291 return result;
292 #else
293 /* Hope for the best */
294 return *--addr;
295 #endif