Cleanup r_string when leaving make_route_string().
[geda-pcb/pcjc2.git] / src / free_atexit.c
blob6c9b94d3f836685cf94f27c2039cde043e960343
1 /*!
2 * \file src/free_atexit.c
4 * \brief .
6 * <hr>
8 * <h1><b>Copyright.</b></h1>\n
10 * Copyright (C) 2010 PCB Contributors (see ChangeLog for details)
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 * Contact addresses for paper mail and Email:
27 * harry eaton, 6697 Buttonhole Ct, Columbia, MD 21044 USA
28 * haceaton@aplcomm.jhuapl.edu
31 #include <stdlib.h>
32 #include <string.h>
34 /*!
35 * \brief We need one ID per context - short int with 64k IDs should be
36 * enough.
38 typedef unsigned int leaky_idx_t;
41 /*!
42 * \brief .
44 * This structure should be as big as void *, which should be the
45 * natural bit-width of the architecture.\n
46 * We allocate extra admin space to be as big as this union, to preserve
47 * alignment of pointers returned by malloc().\n
49 * \note In the special corner case when leaky_idx_t is wider than
50 * void * but not multiple of it, the alignment will be messed up,
51 * potentially causing slower memory access.
53 typedef union {
54 leaky_idx_t idx;
55 void *ptr;
56 } leaky_admin_t;
58 static void **free_list = NULL;
59 static leaky_idx_t free_size = 0;
62 /*!
63 * \brief Allocate memory, remember the pointer and free it after exit
64 * from the application.
66 void *leaky_malloc (size_t size)
68 void *new_memory = malloc(size + sizeof(leaky_admin_t));
70 free_list = (void **)realloc (free_list, (free_size + 1) * sizeof(void *));
71 free_list[free_size] = new_memory;
72 *(leaky_idx_t *)new_memory = free_size;
74 free_size++;
75 return new_memory + sizeof(leaky_admin_t);
78 /*!
79 * \brief Same as leaky_malloc but this one wraps calloc().
81 void *leaky_calloc (size_t nmemb, size_t size)
83 size_t size_ = size * nmemb;
84 void *new_memory = leaky_malloc (size_);
86 memset (new_memory, 0, size_);
87 return new_memory;
90 /*!
91 * \brief Reallocate memory, remember the new pointer and free it after
92 * exit from the application.
94 void *leaky_realloc (void* old_memory, size_t size)
96 void *new_memory;
97 leaky_idx_t i;
99 if (old_memory == NULL)
100 return leaky_malloc (size);
102 old_memory -= sizeof(leaky_admin_t);
104 i = *(leaky_idx_t *)old_memory;
106 new_memory = realloc (old_memory, size + sizeof(leaky_admin_t));
107 free_list[i] = new_memory;
109 return new_memory + sizeof(leaky_admin_t);
113 * \brief Free all allocations.
115 void leaky_uninit (void)
117 int i;
119 for (i = 0; i < free_size; i++)
120 free (free_list[i]);
122 free (free_list);
123 free_size = 0;
127 * \brief Set up atexit() hook.
129 * Can be avoided if leaky_uninit() is called by hand.
131 void leaky_init (void)
133 atexit(leaky_uninit);