1 /*
2 * mpatrol
3 * A library for controlling and tracing dynamic memory allocations.
4 * Copyright (C) 1997-2002 Graeme S. Roy <graeme.roy@analog.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
19 * MA 02111-1307, USA.
20 */
21
22
23 /*
24 * Option handling. Run-time modifiable flags are set here by parsing
25 * an option string read from an environment variable. Any warnings
26 * or errors that occurred during parsing will be reported.
27 */
28
29
30 #include "option.h"
31 #include "diag.h"
32 #include "utils.h"
33 #include <stdlib.h>
34 #include <string.h>
35 #include <ctype.h>
36 #include <errno.h>
37 #include <limits.h>
38 #include <time.h>
39
40
41 #if MP_IDENT_SUPPORT
42 #ident "$Id: option.c,v 1.43 2002/01/08 20:13:59 graeme Exp $"
43 #else /* MP_IDENT_SUPPORT */
44 static MP_CONST MP_VOLATILE char *option_id = "$Id: option.c,v 1.43 2002/01/08 20:13:59 graeme Exp $";
45 #endif /* MP_IDENT_SUPPORT */
46
47
48 #ifdef __cplusplus
49 extern "C"
50 {
51 #endif /* __cplusplus */
52
53
54 /* The temporary buffer used to parse the configuration environment variable,
55 * since if we change the variable directly then we change the environment.
56 * This should not really be a file scope variable as it prevents this module
57 * from being re-entrant.
58 */
59
60 static char options[1024];
61
62
63 /* The table describing a summary of all recognised options.
64 */
65
66 static char *options_help[] =
67 {
68 "ALLOCBYTE", "unsigned integer",
69 "", "Specifies an 8-bit byte pattern with which to prefill newly-allocated",
70 "", "memory.",
71 "ALLOCSTOP", "unsigned integer",
72 "", "Specifies an allocation index at which to stop the program when it is",
73 "", "being allocated.",
74 "ALLOWOFLOW", NULL,
75 "", "Specifies that a warning rather than an error should be produced if",
76 "", "any memory operation function overflows the boundaries of a memory",
77 "", "allocation, and that the operation should still be performed.",
78 "AUTOSAVE", "unsigned integer",
79 "", "Specifies the frequency at which to periodically write the profiling",
80 "", "data to the profiling output file.",
81 "CHECK", "unsigned range",
82 "", "Specifies a range of allocation indices at which to check the",
83 "", "integrity of free memory and overflow buffers.",
84 "CHECKALL", NULL,
85 "", "Equivalent to the CHECKALLOCS, CHECKREALLOCS, CHECKFREES and",
86 "", "CHECKMEMORY options specified together.",
87 "CHECKALLOCS", NULL,
88 "", "Checks that no attempt is made to allocate a block of memory of size",
89 "", "zero.",
90 "CHECKFORK", NULL,
91 "", "Checks at every call to see if the process has been forked in case",
92 "", "new log, profiling and tracing output files need to be started.",
93 "CHECKFREES", NULL,
94 "", "Checks that no attempt is made to deallocate a NULL pointer.",
95 "CHECKMEMORY", NULL,
96 "", "Checks that no attempt is made to perform a zero-length memory",
97 "", "operation on a NULL pointer.",
98 "CHECKREALLOCS", NULL,
99 "", "Checks that no attempt is made to reallocate a NULL pointer or resize",
100 "", "an existing block of memory to size zero.",
101 "DEFALIGN", "unsigned integer",
102 "", "Specifies the default alignment for general-purpose memory",
103 "", "allocations, which must be a power of two.",
104 "EDIT", NULL,
105 "", "Specifies that a text editor should be invoked to edit any relevant",
106 "", "source files that are associated with any warnings or errors when",
107 "", "they occur.",
108 "FAILFREQ", "unsigned integer",
109 "", "Specifies the frequency at which all memory allocations will randomly",
110 "", "fail.",
111 "FAILSEED", "unsigned integer",
112 "", "Specifies the random number seed which will be used when determining",
113 "", "which memory allocations will randomly fail.",
114 "FREEBYTE", "unsigned integer",
115 "", "Specifies an 8-bit byte pattern with which to prefill newly-freed",
116 "", "memory.",
117 "FREESTOP", "unsigned integer",
118 "", "Specifies an allocation index at which to stop the program when it is",
119 "", "being freed.",
120 "HELP", NULL,
121 "", "Displays this quick-reference option summary.",
122 "HTML", NULL,
123 "", "Specifies that the log file should be formatted in HTML.",
124 "LARGEBOUND", "unsigned integer",
125 "", "Specifies the limit in bytes up to which memory allocations should be",
126 "", "classified as large allocations for profiling purposes.",
127 "LEAKTABLE", NULL,
128 "", "Specifies that the leak table should be automatically used and a leak",
129 "", "table summary should be displayed at the end of program execution.",
130 "LIMIT", "unsigned integer",
131 "", "Specifies the limit in bytes at which all memory allocations should",
132 "", "fail if the total allocated memory should increase beyond this.",
133 "LIST", NULL,
134 "", "Specifies that a context listing should be shown for any relevant",
135 "", "source files that are associated with any warnings or errors when",
136 "", "they occur.",
137 "LOGALL", NULL,
138 "", "Equivalent to the LOGALLOCS, LOGREALLOCS, LOGFREES and LOGMEMORY",
139 "", "options specified together.",
140 "LOGALLOCS", NULL,
141 "", "Specifies that all memory allocations are to be logged and sent to",
142 "", "the log file.",
143 "LOGFILE", "string",
144 "", "Specifies an alternative file in which to place all diagnostics from",
145 "", "the mpatrol library.",
146 "LOGFREES", NULL,
147 "", "Specifies that all memory deallocations are to be logged and sent to",
148 "", "the log file.",
149 "LOGMEMORY", NULL,
150 "", "Specifies that all memory operations are to be logged and sent to the",
151 "", "log file.",
152 "LOGREALLOCS", NULL,
153 "", "Specifies that all memory reallocations are to be logged and sent to",
154 "", "the log file.",
155 "MEDIUMBOUND", "unsigned integer",
156 "", "Specifies the limit in bytes up to which memory allocations should be",
157 "", "classified as medium allocations for profiling purposes.",
158 "NOFREE", "unsigned integer",
159 "", "Specifies that a number of recently-freed memory allocations should",
160 "", "be prevented from being returned to the free memory pool.",
161 "NOPROTECT", NULL,
162 "", "Specifies that the mpatrol library's internal data structures should",
163 "", "not be made read-only after every memory allocation, reallocation or",
164 "", "deallocation.",
165 "OFLOWBYTE", "unsigned integer",
166 "", "Specifies an 8-bit byte pattern with which to fill the overflow",
167 "", "buffers of all memory allocations.",
168 "OFLOWSIZE", "unsigned integer",
169 "", "Specifies the size in bytes to use for all overflow buffers, which",
170 "", "must be a power of two.",
171 "OFLOWWATCH", NULL,
172 "", "Specifies that watch point areas should be used for overflow buffers",
173 "", "rather than filling with the overflow byte.",
174 "PAGEALLOC", "LOWER|UPPER",
175 "", "Specifies that each individual memory allocation should occupy at",
176 "", "least one page of virtual memory and should be placed at the lowest",
177 "", "or highest point within these pages.",
178 "PRESERVE", NULL,
179 "", "Specifies that any reallocated or freed memory allocations should",
180 "", "preserve their original contents.",
181 "PROF", NULL,
182 "", "Specifies that all memory allocations are to be profiled and sent to",
183 "", "the profiling output file.",
184 "PROFFILE", "string",
185 "", "Specifies an alternative file in which to place all memory allocation",
186 "", "profiling information from the mpatrol library.",
187 "PROGFILE", "string",
188 "", "Specifies an alternative filename with which to locate the executable",
189 "", "file containing the program's symbols.",
190 "REALLOCSTOP", "unsigned integer",
191 "", "Specifies an allocation index at which to stop the program when a",
192 "", "memory allocation is being reallocated.",
193 "SAFESIGNALS", NULL,
194 "", "Instructs the library to save and replace certain signal handlers",
195 "", "during the execution of library code and to restore them afterwards.",
196 "SHOWALL", NULL,
197 "", "Equivalent to the SHOWFREE, SHOWFREED, SHOWUNFREED, SHOWMAP and",
198 "", "SHOWSYMBOLS options specified together.",
199 "SHOWFREE", NULL,
200 "", "Specifies that a summary of all of the free memory blocks should be",
201 "", "displayed at the end of program execution.",
202 "SHOWFREED", NULL,
203 "", "Specifies that a summary of all of the freed memory allocations",
204 "", "should be displayed at the end of program execution.",
205 "SHOWMAP", NULL,
206 "", "Specifies that a memory map of the entire heap should be displayed at",
207 "", "the end of program execution.",
208 "SHOWSYMBOLS", NULL,
209 "", "Specifies that a summary of all of the function symbols read from the",
210 "", "program's executable file should be displayed at the end of program",
211 "", "execution.",
212 "SHOWUNFREED", NULL,
213 "", "Specifies that a summary of all of the unfreed memory allocations",
214 "", "should be displayed at the end of program execution.",
215 "SMALLBOUND", "unsigned integer",
216 "", "Specifies the limit in bytes up to which memory allocations should be",
217 "", "classified as small allocations for profiling purposes.",
218 "TRACE", NULL,
219 "", "Specifies that all memory allocations are to be traced and sent to",
220 "", "the tracing output file.",
221 "TRACEFILE", "string",
222 "", "Specifies an alternative file in which to place all memory allocation",
223 "", "tracing information from the mpatrol library.",
224 "UNFREEDABORT", "unsigned integer",
225 "", "Specifies the minimum number of unfreed allocations at which to abort",
226 "", "the program just before program termination.",
227 "USEDEBUG", NULL,
228 "", "Specifies that any debugging information in the executable file",
229 "", "should be used to obtain additional source-level information.",
230 "USEMMAP", NULL,
231 "", "Specifies that the library should use mmap() instead of sbrk() to",
232 "", "allocate user memory on UNIX platforms.",
233 NULL
234 };
235
236
237 /* Perform a case-insensitive comparison between two option keywords.
238 */
239
240 static
241 int
matchoption(char * s,char * t)242 matchoption(char *s, char *t)
243 {
244 #if TARGET != TARGET_AMIGA && TARGET != TARGET_WINDOWS && \
245 TARGET != TARGET_NETWARE
246 int d;
247 #endif /* TARGET */
248
249 #if TARGET == TARGET_AMIGA || TARGET == TARGET_WINDOWS || \
250 TARGET == TARGET_NETWARE
251 return !stricmp(s, t);
252 #else /* TARGET */
253 while (((d = toupper(*s) - toupper(*t)) == 0) && (*s != '\0'))
254 {
255 s++;
256 t++;
257 }
258 return (d == 0);
259 #endif /* TARGET */
260 }
261
262
263 /* Convert a string representation of a number to an integer,
264 * reporting any errors that occur during the conversion.
265 */
266
267 static
268 size_t
readnumber(char * s,long * n,int u)269 readnumber(char *s, long *n, int u)
270 {
271 char *t;
272 int e;
273
274 e = errno;
275 errno = 0;
276 while (isspace(*s))
277 s++;
278 if ((u == 1) && (*s == '-'))
279 {
280 __mp_error(ET_MAX, AT_MAX, NULL, 0, "ignoring negative number `%s'\n",
281 s);
282 t = s;
283 }
284 else if ((u == 0) && (*s == '-') && (s[1] == '0') && ((s[2] == 'b') ||
285 (s[2] == 'B')))
286 /* This is a negative binary number.
287 */
288 *n = -strtol(s + 3, &t, 2);
289 else if ((*s == '0') && ((s[1] == 'b') || (s[1] == 'B')))
290 {
291 /* This is a positive binary number.
292 */
293 if (u == 0)
294 *n = strtol(s + 2, &t, 2);
295 else
296 *n = strtoul(s + 2, &t, 2);
297 }
298 /* Otherwise let the conversion function work out the number base
299 * from the prefix.
300 */
301 else if (u == 0)
302 *n = strtol(s, &t, 0);
303 else
304 *n = strtoul(s, &t, 0);
305 if (errno == ERANGE)
306 __mp_warn(ET_MAX, AT_MAX, NULL, 0, "%s number overflow in `%s'\n",
307 ((u == 0) && (*n == LONG_MIN)) ? "negative" : "positive", s);
308 errno = e;
309 return (size_t) (t - s);
310 }
311
312
313 /* Convert a string representation of a numeric range to two unsigned integers,
314 * ensuring that the first integer is less than or equal to the second. An
315 * open range at either end is represented by -1.
316 */
317
318 static
319 int
readrange(char * s,unsigned long * l,unsigned long * u,unsigned long * d)320 readrange(char *s, unsigned long *l, unsigned long *u, unsigned long *d)
321 {
322 char *p, *t;
323 unsigned long n;
324 int w;
325 char b, c;
326
327 w = 0;
328 *l = *u = (unsigned long) -1;
329 *d = 1;
330 for (p = s; (*p != '/') && (*p != '\0'); p++);
331 b = *p;
332 *p = '\0';
333 for (t = s; (*t != '-') && (*t != '\0'); t++);
334 c = *t;
335 *t = '\0';
336 /* If there was a number before the minus sign then read it.
337 */
338 if ((*s != '\0') && (s[readnumber(s, (long *) l, 1)] != '\0'))
339 {
340 *l = (unsigned long) -1;
341 w = 1;
342 }
343 else if (c == '\0')
344 *u = *l;
345 else
346 {
347 s = t + 1;
348 /* If there was a number after the minus sign then read it too.
349 */
350 if ((*s != '\0') && (s[readnumber(s, (long *) u, 1)] != '\0'))
351 {
352 *u = (unsigned long) -1;
353 w = 1;
354 }
355 }
356 if ((w == 0) && (b == '/'))
357 {
358 s = p + 1;
359 /* If there was a forward slash then read the number after it as well.
360 */
361 if ((*s != '\0') && (s[readnumber(s, (long *) d, 1)] != '\0'))
362 {
363 *d = 1;
364 w = 1;
365 }
366 }
367 if (w != 0)
368 return 0;
369 /* If one or the other of the integers was zero (but not both) then convert
370 * it to an open range.
371 */
372 if ((*l == 0) && (*u != 0))
373 *l = (unsigned long) -1;
374 else if ((*l != 0) && (*u == 0))
375 *u = (unsigned long) -1;
376 /* If the frequency was zero then convert it to one.
377 */
378 if (*d == 0)
379 *d = 1;
380 /* Swap the integers if the first number is greater than the second.
381 */
382 if ((*l != (unsigned long) -1) && (*u != (unsigned long) -1) && (*l > *u))
383 {
384 n = *l;
385 *l = *u;
386 *u = n;
387 }
388 return 1;
389 }
390
391
392 /* Display the quick-reference help summary.
393 */
394
395 static
396 void
showoptions(void)397 showoptions(void)
398 {
399 char **s, **t;
400
401 __mp_diag("Available options:\n\n");
402 for (s = options_help, t = s + 1; *s != NULL; s += 2, t += 2)
403 if (**s != '\0')
404 {
405 __mp_diag(" %s", *s);
406 if (*t != NULL)
407 __mp_diag("=<%s>", *t);
408 __mp_diag("\n");
409 }
410 else
411 __mp_diag("\t%s\n", *t);
412 __mp_diag("\n");
413 }
414
415
416 /* The main option parsing routine.
417 */
418
419 MP_GLOBAL
420 void
__mp_parseoptions(infohead * h)421 __mp_parseoptions(infohead *h)
422 {
423 char *a, *f, *o, *p, *s, *t;
424 unsigned long d, m, n;
425 int i, l, q;
426
427 l = 0;
428 f = p = t = NULL;
429 if (((s = getenv(MP_OPTIONS)) == NULL) || (*s == '\0'))
430 return;
431 if (strlen(s) + 1 > sizeof(options))
432 {
433 __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s: environment variable too "
434 "long\n", MP_OPTIONS);
435 return;
436 }
437 /* We shouldn't modify the original string returned by getenv() since
438 * that would modify the environment, and it may be placed in read-only
439 * memory anyway.
440 */
441 strcpy(options, s);
442 s = options;
443 while (*s != '\0')
444 {
445 i = 0;
446 while (isspace(*s))
447 s++;
448 if (*s == '\0')
449 break;
450 if (*s != '=')
451 {
452 /* Scan the option keyword.
453 */
454 for (o = s, q = 0; ((q == 1) || !isspace(*s)) && (*s != '\0') &&
455 (*s != '='); s++)
456 if (*s == '"')
457 {
458 /* Remove any quotes from the keyword.
459 */
460 __mp_memcopy(s, s + 1, strlen(s));
461 q = (q == 0) ? 1 : 0;
462 s--;
463 }
464 if ((*s != '\0') && (*s != '='))
465 {
466 *s++ = '\0';
467 i = 1;
468 }
469 }
470 else
471 o = "";
472 if ((*s == '=') && (i == 0))
473 {
474 /* Scan the option value.
475 */
476 *s++ = '\0';
477 for (a = s, q = 0; ((q == 1) || !isspace(*s)) && (*s != '\0'); s++)
478 if (*s == '"')
479 {
480 /* Remove any quotes from the value.
481 */
482 __mp_memcopy(s, s + 1, strlen(s));
483 q = (q == 0) ? 1 : 0;
484 s--;
485 }
486 if (*s != '\0')
487 *s++ = '\0';
488 }
489 else
490 a = "";
491 if (*o != '\0')
492 {
493 /* We now have an option keyword and possibly an associated
494 * value, so we can now check for valid keywords.
495 */
496 i = OE_UNRECOGNISED;
497 switch (toupper(*o))
498 {
499 case 'A':
500 if (matchoption(o, "ALLOCBYTE"))
501 if (*a == '\0')
502 i = OE_NOARGUMENT;
503 else if (a[readnumber(a, (long *) &n, 1)] != '\0')
504 i = OE_BADNUMBER;
505 else if (n > 0xFF)
506 i = OE_BIGNUMBER;
507 else
508 {
509 h->alloc.abyte = n;
510 i = OE_RECOGNISED;
511 }
512 else if (matchoption(o, "ALLOCSTOP"))
513 if (*a == '\0')
514 i = OE_NOARGUMENT;
515 else if (a[readnumber(a, (long *) &n, 1)] != '\0')
516 i = OE_BADNUMBER;
517 else
518 {
519 h->astop = n;
520 i = OE_RECOGNISED;
521 }
522 else if (matchoption(o, "ALLOWOFLOW"))
523 {
524 if (*a != '\0')
525 i = OE_IGNARGUMENT;
526 else
527 i = OE_RECOGNISED;
528 h->flags |= FLG_ALLOWOFLOW;
529 }
530 else if (matchoption(o, "AUTOSAVE"))
531 if (*a == '\0')
532 i = OE_NOARGUMENT;
533 else if (a[readnumber(a, (long *) &n, 1)] != '\0')
534 i = OE_BADNUMBER;
535 else
536 {
537 h->prof.autosave = n;
538 i = OE_RECOGNISED;
539 }
540 break;
541 case 'C':
542 if (matchoption(o, "CHECK"))
543 if (*a == '\0')
544 i = OE_NOARGUMENT;
545 else if (!readrange(a, &m, &n, &d))
546 i = OE_BADRANGE;
547 else
548 {
549 h->lrange = m;
550 h->urange = n;
551 h->check = d;
552 i = OE_RECOGNISED;
553 }
554 else if (matchoption(o, "CHECKALL"))
555 {
556 if (*a != '\0')
557 i = OE_IGNARGUMENT;
558 else
559 i = OE_RECOGNISED;
560 h->flags |= FLG_CHECKALLOCS | FLG_CHECKREALLOCS |
561 FLG_CHECKFREES | FLG_CHECKMEMORY;
562 }
563 else if (matchoption(o, "CHECKALLOCS"))
564 {
565 if (*a != '\0')
566 i = OE_IGNARGUMENT;
567 else
568 i = OE_RECOGNISED;
569 h->flags |= FLG_CHECKALLOCS;
570 }
571 else if (matchoption(o, "CHECKFORK"))
572 {
573 if (*a != '\0')
574 i = OE_IGNARGUMENT;
575 else
576 i = OE_RECOGNISED;
577 h->flags |= FLG_CHECKFORK;
578 }
579 else if (matchoption(o, "CHECKFREES"))
580 {
581 if (*a != '\0')
582 i = OE_IGNARGUMENT;
583 else
584 i = OE_RECOGNISED;
585 h->flags |= FLG_CHECKFREES;
586 }
587 else if (matchoption(o, "CHECKMEMORY"))
588 {
589 if (*a != '\0')
590 i = OE_IGNARGUMENT;
591 else
592 i = OE_RECOGNISED;
593 h->flags |= FLG_CHECKMEMORY;
594 }
595 else if (matchoption(o, "CHECKREALLOCS"))
596 {
597 if (*a != '\0')
598 i = OE_IGNARGUMENT;
599 else
600 i = OE_RECOGNISED;
601 h->flags |= FLG_CHECKREALLOCS;
602 }
603 break;
604 case 'D':
605 if (matchoption(o, "DEFALIGN"))
606 if (*a == '\0')
607 i = OE_NOARGUMENT;
608 else if ((a[readnumber(a, (long *) &n, 1)] != '\0') ||
609 (n == 0))
610 i = OE_BADNUMBER;
611 else if (n > h->alloc.heap.memory.page)
612 i = OE_BIGNUMBER;
613 else
614 {
615 h->alloc.heap.memory.align = __mp_poweroftwo(n);
616 i = OE_RECOGNISED;
617 }
618 break;
619 case 'E':
620 if (matchoption(o, "EDIT"))
621 {
622 if (*a != '\0')
623 i = OE_IGNARGUMENT;
624 else
625 i = OE_RECOGNISED;
626 #if TARGET == TARGET_UNIX
627 __mp_diagflags &= ~FLG_LIST;
628 __mp_diagflags |= FLG_EDIT;
629 #endif /* TARGET */
630 }
631 break;
632 case 'F':
633 if (matchoption(o, "FAILFREQ"))
634 if (*a == '\0')
635 i = OE_NOARGUMENT;
636 else if (a[readnumber(a, (long *) &n, 1)] != '\0')
637 i = OE_BADNUMBER;
638 else
639 {
640 h->ffreq = n;
641 i = OE_RECOGNISED;
642 }
643 else if (matchoption(o, "FAILSEED"))
644 if (*a == '\0')
645 i = OE_NOARGUMENT;
646 else if (a[readnumber(a, (long *) &n, 1)] != '\0')
647 i = OE_BADNUMBER;
648 else
649 {
650 h->fseed = n;
651 i = OE_RECOGNISED;
652 }
653 else if (matchoption(o, "FREEBYTE"))
654 if (*a == '\0')
655 i = OE_NOARGUMENT;
656 else if (a[readnumber(a, (long *) &n, 1)] != '\0')
657 i = OE_BADNUMBER;
658 else if (n > 0xFF)
659 i = OE_BIGNUMBER;
660 else
661 {
662 h->alloc.fbyte = n;
663 i = OE_RECOGNISED;
664 }
665 else if (matchoption(o, "FREESTOP"))
666 if (*a == '\0')
667 i = OE_NOARGUMENT;
668 else if (a[readnumber(a, (long *) &n, 1)] != '\0')
669 i = OE_BADNUMBER;
670 else
671 {
672 h->fstop = n;
673 i = OE_RECOGNISED;
674 }
675 break;
676 case 'H':
677 if (matchoption(o, "HELP"))
678 {
679 if (*a != '\0')
680 i = OE_IGNARGUMENT;
681 else
682 i = OE_RECOGNISED;
683 l = 1;
684 }
685 else if (matchoption(o, "HTML"))
686 {
687 if (*a != '\0')
688 i = OE_IGNARGUMENT;
689 else
690 i = OE_RECOGNISED;
691 __mp_diagflags |= FLG_HTMLNEXT;
692 }
693 break;
694 case 'L':
695 if (matchoption(o, "LARGEBOUND"))
696 if (*a == '\0')
697 i = OE_NOARGUMENT;
698 else if (a[readnumber(a, (long *) &n, 1)] != '\0')
699 i = OE_BADNUMBER;
700 else
701 {
702 if (n == 0)
703 h->prof.lbound = MP_LARGEBOUND;
704 else
705 h->prof.lbound = n;
706 i = OE_RECOGNISED;
707 }
708 else if (matchoption(o, "LEAKTABLE"))
709 {
710 if (*a != '\0')
711 i = OE_IGNARGUMENT;
712 else
713 i = OE_RECOGNISED;
714 h->flags |= FLG_LEAKTABLE;
715 }
716 else if (matchoption(o, "LIMIT"))
717 if (*a == '\0')
718 i = OE_NOARGUMENT;
719 else if (a[readnumber(a, (long *) &n, 1)] != '\0')
720 i = OE_BADNUMBER;
721 else
722 {
723 h->limit = n;
724 i = OE_RECOGNISED;
725 }
726 else if (matchoption(o, "LIST"))
727 {
728 if (*a != '\0')
729 i = OE_IGNARGUMENT;
730 else
731 i = OE_RECOGNISED;
732 #if TARGET == TARGET_UNIX
733 __mp_diagflags &= ~FLG_EDIT;
734 __mp_diagflags |= FLG_LIST;
735 #endif /* TARGET */
736 }
737 else if (matchoption(o, "LOGALL"))
738 {
739 if (*a != '\0')
740 i = OE_IGNARGUMENT;
741 else
742 i = OE_RECOGNISED;
743 h->flags |= FLG_LOGALLOCS | FLG_LOGREALLOCS | FLG_LOGFREES |
744 FLG_LOGMEMORY;
745 }
746 else if (matchoption(o, "LOGALLOCS"))
747 {
748 if (*a != '\0')
749 i = OE_IGNARGUMENT;
750 else
751 i = OE_RECOGNISED;
752 h->flags |= FLG_LOGALLOCS;
753 }
754 else if (matchoption(o, "LOGFILE"))
755 if (*a == '\0')
756 i = OE_NOARGUMENT;
757 else
758 {
759 f = a;
760 i = OE_RECOGNISED;
761 }
762 else if (matchoption(o, "LOGFREES"))
763 {
764 if (*a != '\0')
765 i = OE_IGNARGUMENT;
766 else
767 i = OE_RECOGNISED;
768 h->flags |= FLG_LOGFREES;
769 }
770 else if (matchoption(o, "LOGMEMORY"))
771 {
772 if (*a != '\0')
773 i = OE_IGNARGUMENT;
774 else
775 i = OE_RECOGNISED;
776 h->flags |= FLG_LOGMEMORY;
777 }
778 else if (matchoption(o, "LOGREALLOCS"))
779 {
780 if (*a != '\0')
781 i = OE_IGNARGUMENT;
782 else
783 i = OE_RECOGNISED;
784 h->flags |= FLG_LOGREALLOCS;
785 }
786 break;
787 case 'M':
788 if (matchoption(o, "MEDIUMBOUND"))
789 if (*a == '\0')
790 i = OE_NOARGUMENT;
791 else if (a[readnumber(a, (long *) &n, 1)] != '\0')
792 i = OE_BADNUMBER;
793 else
794 {
795 if (n == 0)
796 h->prof.mbound = MP_MEDIUMBOUND;
797 else
798 h->prof.mbound = n;
799 i = OE_RECOGNISED;
800 }
801 break;
802 case 'N':
803 if (matchoption(o, "NOFREE"))
804 if (*a == '\0')
805 i = OE_NOARGUMENT;
806 else if (a[readnumber(a, (long *) &n, 1)] != '\0')
807 i = OE_BADNUMBER;
808 else
809 {
810 if (h->alloc.fmax = n)
811 h->alloc.flags |= FLG_NOFREE;
812 else
813 h->alloc.flags &= ~FLG_NOFREE;
814 i = OE_RECOGNISED;
815 }
816 else if (matchoption(o, "NOPROTECT"))
817 {
818 if (*a != '\0')
819 i = OE_IGNARGUMENT;
820 else
821 i = OE_RECOGNISED;
822 h->flags |= FLG_NOPROTECT;
823 }
824 break;
825 case 'O':
826 if (matchoption(o, "OFLOWBYTE"))
827 if (*a == '\0')
828 i = OE_NOARGUMENT;
829 else if (a[readnumber(a, (long *) &n, 1)] != '\0')
830 i = OE_BADNUMBER;
831 else if (n > 0xFF)
832 i = OE_BIGNUMBER;
833 else
834 {
835 h->alloc.obyte = n;
836 i = OE_RECOGNISED;
837 }
838 else if (matchoption(o, "OFLOWSIZE"))
839 if (*a == '\0')
840 i = OE_NOARGUMENT;
841 else if ((a[readnumber(a, (long *) &n, 1)] != '\0') ||
842 ((n == 0) && (h->alloc.flags & FLG_PAGEALLOC)))
843 i = OE_BADNUMBER;
844 else
845 {
846 h->alloc.oflow = __mp_poweroftwo(n);
847 if (h->alloc.flags & FLG_PAGEALLOC)
848 h->alloc.oflow = __mp_roundup(h->alloc.oflow,
849 h->alloc.heap.memory.page);
850 i = OE_RECOGNISED;
851 }
852 else if (matchoption(o, "OFLOWWATCH"))
853 {
854 if (*a != '\0')
855 i = OE_IGNARGUMENT;
856 else
857 i = OE_RECOGNISED;
858 #if MP_WATCH_SUPPORT
859 h->alloc.flags |= FLG_OFLOWWATCH;
860 #endif /* MP_WATCH_SUPPORT */
861 }
862 break;
863 case 'P':
864 if (matchoption(o, "PAGEALLOC"))
865 if (*a == '\0')
866 i = OE_NOARGUMENT;
867 else if (matchoption(a, "LOWER"))
868 {
869 #if MP_PROTECT_SUPPORT
870 h->alloc.flags |= FLG_PAGEALLOC;
871 if (h->alloc.oflow == 0)
872 h->alloc.oflow = 1;
873 h->alloc.oflow = __mp_roundup(h->alloc.oflow,
874 h->alloc.heap.memory.page);
875 #endif /* MP_PROTECT_SUPPORT */
876 i = OE_RECOGNISED;
877 }
878 else if (matchoption(a, "UPPER"))
879 {
880 #if MP_PROTECT_SUPPORT
881 h->alloc.flags |= FLG_PAGEALLOC | FLG_ALLOCUPPER;
882 if (h->alloc.oflow == 0)
883 h->alloc.oflow = 1;
884 h->alloc.oflow = __mp_roundup(h->alloc.oflow,
885 h->alloc.heap.memory.page);
886 #endif /* MP_PROTECT_SUPPORT */
887 i = OE_RECOGNISED;
888 }
889 else
890 i = OE_LOWERORUPPER;
891 else if (matchoption(o, "PRESERVE"))
892 {
893 if (*a != '\0')
894 i = OE_IGNARGUMENT;
895 else
896 i = OE_RECOGNISED;
897 h->alloc.flags |= FLG_PRESERVE;
898 }
899 else if (matchoption(o, "PROF"))
900 {
901 if (*a != '\0')
902 i = OE_IGNARGUMENT;
903 else
904 i = OE_RECOGNISED;
905 h->prof.profiling = 1;
906 }
907 else if (matchoption(o, "PROFFILE"))
908 if (*a == '\0')
909 i = OE_NOARGUMENT;
910 else
911 {
912 p = a;
913 i = OE_RECOGNISED;
914 }
915 else if (matchoption(o, "PROGFILE"))
916 if (*a == '\0')
917 i = OE_NOARGUMENT;
918 else
919 {
920 h->alloc.heap.memory.prog = a;
921 i = OE_RECOGNISED;
922 }
923 break;
924 case 'R':
925 if (matchoption(o, "REALLOCSTOP"))
926 if (*a == '\0')
927 i = OE_NOARGUMENT;
928 else if (a[readnumber(a, (long *) &n, 1)] != '\0')
929 i = OE_BADNUMBER;
930 else
931 {
932 h->rstop = n;
933 i = OE_RECOGNISED;
934 }
935 break;
936 case 'S':
937 if (matchoption(o, "SAFESIGNALS"))
938 {
939 if (*a != '\0')
940 i = OE_IGNARGUMENT;
941 else
942 i = OE_RECOGNISED;
943 h->flags |= FLG_SAFESIGNALS;
944 }
945 else if (matchoption(o, "SHOWALL"))
946 {
947 if (*a != '\0')
948 i = OE_IGNARGUMENT;
949 else
950 i = OE_RECOGNISED;
951 h->flags |= FLG_SHOWFREE | FLG_SHOWFREED | FLG_SHOWUNFREED |
952 FLG_SHOWMAP | FLG_SHOWSYMBOLS;
953 }
954 else if (matchoption(o, "SHOWFREE"))
955 {
956 if (*a != '\0')
957 i = OE_IGNARGUMENT;
958 else
959 i = OE_RECOGNISED;
960 h->flags |= FLG_SHOWFREE;
961 }
962 else if (matchoption(o, "SHOWFREED"))
963 {
964 if (*a != '\0')
965 i = OE_IGNARGUMENT;
966 else
967 i = OE_RECOGNISED;
968 h->flags |= FLG_SHOWFREED;
969 }
970 else if (matchoption(o, "SHOWMAP"))
971 {
972 if (*a != '\0')
973 i = OE_IGNARGUMENT;
974 else
975 i = OE_RECOGNISED;
976 h->flags |= FLG_SHOWMAP;
977 }
978 else if (matchoption(o, "SHOWSYMBOLS"))
979 {
980 if (*a != '\0')
981 i = OE_IGNARGUMENT;
982 else
983 i = OE_RECOGNISED;
984 h->flags |= FLG_SHOWSYMBOLS;
985 }
986 else if (matchoption(o, "SHOWUNFREED"))
987 {
988 if (*a != '\0')
989 i = OE_IGNARGUMENT;
990 else
991 i = OE_RECOGNISED;
992 h->flags |= FLG_SHOWUNFREED;
993 }
994 else if (matchoption(o, "SMALLBOUND"))
995 if (*a == '\0')
996 i = OE_NOARGUMENT;
997 else if (a[readnumber(a, (long *) &n, 1)] != '\0')
998 i = OE_BADNUMBER;
999 else
1000 {
1001 if (n == 0)
1002 h->prof.sbound = MP_SMALLBOUND;
1003 else
1004 h->prof.sbound = n;
1005 i = OE_RECOGNISED;
1006 }
1007 break;
1008 case 'T':
1009 if (matchoption(o, "TRACE"))
1010 {
1011 if (*a != '\0')
1012 i = OE_IGNARGUMENT;
1013 else
1014 i = OE_RECOGNISED;
1015 h->trace.tracing = 1;
1016 h->alloc.heap.tracing = 1;
1017 }
1018 else if (matchoption(o, "TRACEFILE"))
1019 if (*a == '\0')
1020 i = OE_NOARGUMENT;
1021 else
1022 {
1023 t = a;
1024 i = OE_RECOGNISED;
1025 }
1026 break;
1027 case 'U':
1028 if (matchoption(o, "UNFREEDABORT"))
1029 if (*a == '\0')
1030 i = OE_NOARGUMENT;
1031 else if (a[readnumber(a, (long *) &n, 1)] != '\0')
1032 i = OE_BADNUMBER;
1033 else
1034 {
1035 h->uabort = n;
1036 i = OE_RECOGNISED;
1037 }
1038 else if (matchoption(o, "USEDEBUG"))
1039 {
1040 if (*a != '\0')
1041 i = OE_IGNARGUMENT;
1042 else
1043 i = OE_RECOGNISED;
1044 h->syms.lineinfo = 1;
1045 }
1046 else if (matchoption(o, "USEMMAP"))
1047 {
1048 if (*a != '\0')
1049 i = OE_IGNARGUMENT;
1050 else
1051 i = OE_RECOGNISED;
1052 #if MP_MMAP_SUPPORT
1053 if (h->alloc.list.size == 0)
1054 h->alloc.heap.memory.flags |= FLG_USEMMAP;
1055 #endif /* MP_MMAP_SUPPORT */
1056 }
1057 break;
1058 default:
1059 break;
1060 }
1061 /* Now check the error code returned from attempting to match
1062 * the keyword and report if anything went wrong.
1063 */
1064 switch (i)
1065 {
1066 case OE_UNRECOGNISED:
1067 if (*a == '\0')
1068 __mp_error(ET_MAX, AT_MAX, NULL, 0, "unrecognised option "
1069 "`%s'\n", o);
1070 else
1071 __mp_error(ET_MAX, AT_MAX, NULL, 0, "unrecognised option "
1072 "`%s=%s'\n", o, a);
1073 break;
1074 case OE_NOARGUMENT:
1075 __mp_error(ET_MAX, AT_MAX, NULL, 0, "missing argument for "
1076 "option `%s'\n", o);
1077 break;
1078 case OE_BADNUMBER:
1079 __mp_error(ET_MAX, AT_MAX, NULL, 0, "bad numeric argument `%s' "
1080 "for option `%s'\n", a, o);
1081 break;
1082 case OE_BADRANGE:
1083 __mp_error(ET_MAX, AT_MAX, NULL, 0, "bad numeric range `%s' "
1084 "for option `%s'\n", a, o);
1085 break;
1086 case OE_BIGNUMBER:
1087 __mp_error(ET_MAX, AT_MAX, NULL, 0, "numeric argument `%s' is "
1088 "too large for option `%s'\n", a, o);
1089 break;
1090 case OE_LOWERORUPPER:
1091 __mp_error(ET_MAX, AT_MAX, NULL, 0, "must specify `LOWER' or "
1092 "`UPPER' for option `%s'\n", o);
1093 break;
1094 case OE_IGNARGUMENT:
1095 __mp_warn(ET_MAX, AT_MAX, NULL, 0, "ignoring argument `%s' for "
1096 "option `%s'\n", a, o);
1097 break;
1098 default:
1099 break;
1100 }
1101 }
1102 else if (*a != '\0')
1103 __mp_warn(ET_MAX, AT_MAX, NULL, 0, "missing option for argument "
1104 "`%s'\n", a);
1105 }
1106 /* Check the validity of the profiling allocation boundaries. There is
1107 * potential for error if either of the small or large bounds overlap the
1108 * medium bound and the medium bound is either 1 or the maximum sized
1109 * integer, but it will just result in wrong profiling and nothing more.
1110 */
1111 if (h->prof.sbound >= h->prof.mbound)
1112 {
1113 __mp_error(ET_MAX, AT_MAX, NULL, 0, "small allocation boundary `%lu' "
1114 "overlaps medium allocation boundary `%lu'\n",
1115 h->prof.sbound, h->prof.mbound);
1116 h->prof.sbound = h->prof.mbound - 1;
1117 }
1118 if (h->prof.lbound <= h->prof.mbound)
1119 {
1120 __mp_error(ET_MAX, AT_MAX, NULL, 0, "large allocation boundary `%lu' "
1121 "overlaps medium allocation boundary `%lu'\n",
1122 h->prof.lbound, h->prof.mbound);
1123 h->prof.lbound = h->prof.mbound + 1;
1124 }
1125 /* Show the quick-reference option summary if it was requested.
1126 */
1127 if (l != 0)
1128 showoptions();
1129 /* Set up the filenames of the log, profiling and tracing files if they
1130 * were overridden.
1131 */
1132 if (f != NULL)
1133 h->log = __mp_logfile(&h->alloc.heap.memory, f);
1134 if (p != NULL)
1135 h->prof.file = __mp_proffile(&h->alloc.heap.memory, p);
1136 if (t != NULL)
1137 h->trace.file = __mp_tracefile(&h->alloc.heap.memory, t);
1138 }
1139
1140
1141 /* Set mpatrol flags after the library has been initialised.
1142 */
1143
1144 static
1145 unsigned long
setflags(infohead * h,unsigned long f,int u)1146 setflags(infohead *h, unsigned long f, int u)
1147 {
1148 unsigned long i;
1149
1150 if (f == 0)
1151 return 0;
1152 for (i = 1; i != 0; i <<= 1)
1153 if (f & i)
1154 {
1155 f &= ~i;
1156 switch (i)
1157 {
1158 case OPT_CHECKALLOCS:
1159 if (u == 0)
1160 h->flags |= FLG_CHECKALLOCS;
1161 else
1162 h->flags &= ~FLG_CHECKALLOCS;
1163 break;
1164 case OPT_CHECKREALLOCS:
1165 if (u == 0)
1166 h->flags |= FLG_CHECKREALLOCS;
1167 else
1168 h->flags &= ~FLG_CHECKREALLOCS;
1169 break;
1170 case OPT_CHECKFREES:
1171 if (u == 0)
1172 h->flags |= FLG_CHECKFREES;
1173 else
1174 h->flags &= ~FLG_CHECKFREES;
1175 break;
1176 case OPT_CHECKMEMORY:
1177 if (u == 0)
1178 h->flags |= FLG_CHECKMEMORY;
1179 else
1180 h->flags &= ~FLG_CHECKMEMORY;
1181 break;
1182 case OPT_LOGALLOCS:
1183 if (u == 0)
1184 h->flags |= FLG_LOGALLOCS;
1185 else
1186 h->flags &= ~FLG_LOGALLOCS;
1187 break;
1188 case OPT_LOGREALLOCS:
1189 if (u == 0)
1190 h->flags |= FLG_LOGREALLOCS;
1191 else
1192 h->flags &= ~FLG_LOGREALLOCS;
1193 break;
1194 case OPT_LOGFREES:
1195 if (u == 0)
1196 h->flags |= FLG_LOGFREES;
1197 else
1198 h->flags &= ~FLG_LOGFREES;
1199 break;
1200 case OPT_LOGMEMORY:
1201 if (u == 0)
1202 h->flags |= FLG_LOGMEMORY;
1203 else
1204 h->flags &= ~FLG_LOGMEMORY;
1205 break;
1206 case OPT_SHOWMAP:
1207 if (u == 0)
1208 h->flags |= FLG_SHOWMAP;
1209 else
1210 h->flags &= ~FLG_SHOWMAP;
1211 break;
1212 case OPT_SHOWSYMBOLS:
1213 if (u == 0)
1214 h->flags |= FLG_SHOWSYMBOLS;
1215 else
1216 h->flags &= ~FLG_SHOWSYMBOLS;
1217 break;
1218 case OPT_SHOWFREE:
1219 if (u == 0)
1220 h->flags |= FLG_SHOWFREE;
1221 else
1222 h->flags &= ~FLG_SHOWFREE;
1223 break;
1224 case OPT_SHOWFREED:
1225 if (u == 0)
1226 h->flags |= FLG_SHOWFREED;
1227 else
1228 h->flags &= ~FLG_SHOWFREED;
1229 break;
1230 case OPT_SHOWUNFREED:
1231 if (u == 0)
1232 h->flags |= FLG_SHOWUNFREED;
1233 else
1234 h->flags &= ~FLG_SHOWUNFREED;
1235 break;
1236 case OPT_LEAKTABLE:
1237 if (u == 0)
1238 {
1239 h->flags |= FLG_LEAKTABLE;
1240 h->ltable.tracing = 1;
1241 }
1242 else
1243 {
1244 h->flags &= ~FLG_LEAKTABLE;
1245 h->ltable.tracing = 0;
1246 }
1247 break;
1248 case OPT_ALLOWOFLOW:
1249 if (u == 0)
1250 h->flags |= FLG_ALLOWOFLOW;
1251 else
1252 h->flags &= ~FLG_ALLOWOFLOW;
1253 break;
1254 case OPT_CHECKFORK:
1255 if (u == 0)
1256 h->flags |= FLG_CHECKFORK;
1257 else
1258 h->flags &= ~FLG_CHECKFORK;
1259 break;
1260 case OPT_EDIT:
1261 if (u == 0)
1262 {
1263 #if TARGET == TARGET_UNIX
1264 __mp_diagflags &= ~FLG_LIST;
1265 __mp_diagflags |= FLG_EDIT;
1266 #endif /* TARGET */
1267 }
1268 else
1269 {
1270 #if TARGET == TARGET_UNIX
1271 __mp_diagflags &= ~FLG_EDIT;
1272 #endif /* TARGET */
1273 }
1274 break;
1275 case OPT_LIST:
1276 if (u == 0)
1277 {
1278 #if TARGET == TARGET_UNIX
1279 __mp_diagflags &= ~FLG_EDIT;
1280 __mp_diagflags |= FLG_LIST;
1281 #endif /* TARGET */
1282 }
1283 else
1284 {
1285 #if TARGET == TARGET_UNIX
1286 __mp_diagflags &= ~FLG_LIST;
1287 #endif /* TARGET */
1288 }
1289 break;
1290 default:
1291 f |= i;
1292 break;
1293 }
1294 }
1295 return f;
1296 }
1297
1298
1299 /* Set an mpatrol option after the library has been initialised.
1300 */
1301
1302 MP_GLOBAL
1303 unsigned long
__mp_set(infohead * h,unsigned long o,unsigned long v)1304 __mp_set(infohead *h, unsigned long o, unsigned long v)
1305 {
1306 unsigned long r;
1307
1308 r = 0;
1309 switch (o)
1310 {
1311 case OPT_HELP:
1312 showoptions();
1313 break;
1314 case OPT_SETFLAGS:
1315 r = setflags(h, v, 0);
1316 break;
1317 case OPT_UNSETFLAGS:
1318 r = setflags(h, v, 1);
1319 break;
1320 case OPT_ALLOCSTOP:
1321 h->astop = v;
1322 break;
1323 case OPT_REALLOCSTOP:
1324 h->rstop = v;
1325 break;
1326 case OPT_FREESTOP:
1327 h->fstop = v;
1328 break;
1329 case OPT_ALLOCBYTE:
1330 if (v > 0xFF)
1331 v = 0xFF;
1332 h->alloc.abyte = v;
1333 break;
1334 case OPT_DEFALIGN:
1335 if ((v == 0) || (v > h->alloc.heap.memory.page))
1336 r = o;
1337 else
1338 h->alloc.heap.memory.align = __mp_poweroftwo(v);
1339 break;
1340 case OPT_LIMIT:
1341 h->limit = v;
1342 break;
1343 case OPT_FAILFREQ:
1344 h->ffreq = v;
1345 break;
1346 case OPT_FAILSEED:
1347 if (v == 0)
1348 v = (unsigned long) time(NULL);
1349 srand((unsigned int) v);
1350 h->fseed = v;
1351 break;
1352 case OPT_UNFREEDABORT:
1353 h->uabort = v;
1354 break;
1355 case OPT_AUTOSAVE:
1356 if (h->prof.autocount > 0)
1357 __mp_writeprofile(&h->prof, !(h->flags & FLG_NOPROTECT));
1358 h->prof.autosave = v;
1359 break;
1360 case OPT_CHECKLOWER:
1361 h->lrange = v;
1362 break;
1363 case OPT_CHECKUPPER:
1364 h->urange = v;
1365 break;
1366 case OPT_CHECKFREQ:
1367 if (v == 0)
1368 v = 1;
1369 h->check = v;
1370 break;
1371 case OPT_NOFREE:
1372 while (h->alloc.flist.size > v)
1373 __mp_recyclefreed(&h->alloc);
1374 if (h->alloc.fmax = v)
1375 h->alloc.flags |= FLG_NOFREE;
1376 else
1377 h->alloc.flags &= ~FLG_NOFREE;
1378 break;
1379 default:
1380 r = o;
1381 break;
1382 }
1383 return r;
1384 }
1385
1386
1387 /* Get mpatrol flags after the library has been initialised.
1388 */
1389
1390 static
1391 unsigned long
getflags(infohead * h)1392 getflags(infohead *h)
1393 {
1394 unsigned long f;
1395
1396 f = 0;
1397 if (h->flags & FLG_CHECKALLOCS)
1398 f |= OPT_CHECKALLOCS;
1399 if (h->flags & FLG_CHECKREALLOCS)
1400 f |= OPT_CHECKREALLOCS;
1401 if (h->flags & FLG_CHECKFREES)
1402 f |= OPT_CHECKFREES;
1403 if (h->flags & FLG_CHECKMEMORY)
1404 f |= OPT_CHECKMEMORY;
1405 if (h->flags & FLG_LOGALLOCS)
1406 f |= OPT_LOGALLOCS;
1407 if (h->flags & FLG_LOGREALLOCS)
1408 f |= OPT_LOGREALLOCS;
1409 if (h->flags & FLG_LOGFREES)
1410 f |= OPT_LOGFREES;
1411 if (h->flags & FLG_LOGMEMORY)
1412 f |= OPT_LOGMEMORY;
1413 if (h->flags & FLG_SHOWMAP)
1414 f |= OPT_SHOWMAP;
1415 if (h->flags & FLG_SHOWSYMBOLS)
1416 f |= OPT_SHOWSYMBOLS;
1417 if (h->flags & FLG_SHOWFREE)
1418 f |= OPT_SHOWFREE;
1419 if (h->flags & FLG_SHOWFREED)
1420 f |= OPT_SHOWFREED;
1421 if (h->flags & FLG_SHOWUNFREED)
1422 f |= OPT_SHOWUNFREED;
1423 if (h->flags & FLG_LEAKTABLE)
1424 f |= OPT_LEAKTABLE;
1425 if (h->flags & FLG_ALLOWOFLOW)
1426 f |= OPT_ALLOWOFLOW;
1427 if (h->prof.profiling)
1428 f |= OPT_PROF;
1429 if (h->trace.tracing)
1430 f |= OPT_TRACE;
1431 if (h->flags & FLG_SAFESIGNALS)
1432 f |= OPT_SAFESIGNALS;
1433 if (h->flags & FLG_NOPROTECT)
1434 f |= OPT_NOPROTECT;
1435 if (h->flags & FLG_CHECKFORK)
1436 f |= OPT_CHECKFORK;
1437 if (h->alloc.flags & FLG_PRESERVE)
1438 f |= OPT_PRESERVE;
1439 if (h->alloc.flags & FLG_OFLOWWATCH)
1440 f |= OPT_OFLOWWATCH;
1441 if (h->alloc.flags & FLG_PAGEALLOC)
1442 f |= OPT_PAGEALLOC;
1443 if (h->alloc.flags & FLG_ALLOCUPPER)
1444 f |= OPT_ALLOCUPPER;
1445 if (h->alloc.heap.memory.flags & FLG_USEMMAP)
1446 f |= OPT_USEMMAP;
1447 if (h->syms.lineinfo)
1448 f |= OPT_USEDEBUG;
1449 if (__mp_diagflags & FLG_EDIT)
1450 f |= OPT_EDIT;
1451 if (__mp_diagflags & FLG_LIST)
1452 f |= OPT_LIST;
1453 if (__mp_diagflags & FLG_HTML)
1454 f |= OPT_HTML;
1455 return f;
1456 }
1457
1458
1459 /* Get an mpatrol option after the library has been initialised.
1460 */
1461
1462 MP_GLOBAL
1463 int
__mp_get(infohead * h,unsigned long o,unsigned long * v)1464 __mp_get(infohead *h, unsigned long o, unsigned long *v)
1465 {
1466 int r;
1467
1468 r = 1;
1469 switch (o)
1470 {
1471 case OPT_HELP:
1472 *v = 0;
1473 break;
1474 case OPT_SETFLAGS:
1475 *v = getflags(h);
1476 break;
1477 case OPT_UNSETFLAGS:
1478 *v = ~getflags(h);
1479 break;
1480 case OPT_ALLOCSTOP:
1481 *v = h->astop;
1482 break;
1483 case OPT_REALLOCSTOP:
1484 *v = h->rstop;
1485 break;
1486 case OPT_FREESTOP:
1487 *v = h->fstop;
1488 break;
1489 case OPT_ALLOCBYTE:
1490 *v = h->alloc.abyte;
1491 break;
1492 case OPT_FREEBYTE:
1493 *v = h->alloc.fbyte;
1494 break;
1495 case OPT_OFLOWBYTE:
1496 *v = h->alloc.obyte;
1497 break;
1498 case OPT_OFLOWSIZE:
1499 *v = h->alloc.oflow;
1500 break;
1501 case OPT_DEFALIGN:
1502 *v = h->alloc.heap.memory.align;
1503 break;
1504 case OPT_LIMIT:
1505 *v = h->limit;
1506 break;
1507 case OPT_FAILFREQ:
1508 *v = h->ffreq;
1509 break;
1510 case OPT_FAILSEED:
1511 *v = h->fseed;
1512 break;
1513 case OPT_UNFREEDABORT:
1514 *v = h->uabort;
1515 break;
1516 case OPT_LOGFILE:
1517 *v = (unsigned long) h->log;
1518 break;
1519 case OPT_PROFFILE:
1520 *v = (unsigned long) h->prof.file;
1521 break;
1522 case OPT_TRACEFILE:
1523 *v = (unsigned long) h->trace.file;
1524 break;
1525 case OPT_PROGFILE:
1526 *v = (unsigned long) h->alloc.heap.memory.prog;
1527 break;
1528 case OPT_AUTOSAVE:
1529 *v = h->prof.autosave;
1530 break;
1531 case OPT_CHECKLOWER:
1532 *v = h->lrange;
1533 break;
1534 case OPT_CHECKUPPER:
1535 *v = h->urange;
1536 break;
1537 case OPT_CHECKFREQ:
1538 *v = h->check;
1539 break;
1540 case OPT_NOFREE:
1541 *v = h->alloc.fmax;
1542 break;
1543 case OPT_SMALLBOUND:
1544 *v = h->prof.sbound;
1545 break;
1546 case OPT_MEDIUMBOUND:
1547 *v = h->prof.mbound;
1548 break;
1549 case OPT_LARGEBOUND:
1550 *v = h->prof.lbound;
1551 break;
1552 default:
1553 r = 0;
1554 break;
1555 }
1556 return r;
1557 }
1558
1559
1560 #ifdef __cplusplus
1561 }
1562 #endif /* __cplusplus */
1563