1 /*  Boolector: Satisfiability Modulo Theories (SMT) solver.
2  *
3  *  Copyright (C) 2007-2021 by the authors listed in the AUTHORS file.
4  *
5  *  This file is part of Boolector.
6  *  See COPYING for more information on using this software.
7  */
8 
9 #include "btormem.h"
10 
11 #include "btorabort.h"
12 
13 #include <assert.h>
14 #include <stdarg.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 
19 /*------------------------------------------------------------------------*/
20 
21 #define ADJUST()                                                            \
22   do                                                                        \
23   {                                                                         \
24     if (mm->maxallocated < mm->allocated) mm->maxallocated = mm->allocated; \
25   } while (0)
26 
27 #define SAT_ADJUST()                              \
28   do                                              \
29   {                                               \
30     if (mm->sat_maxallocated < mm->sat_allocated) \
31       mm->sat_maxallocated = mm->sat_allocated;   \
32   } while (0)
33 
34 /*------------------------------------------------------------------------*/
35 /* This enables logging of all memory allocations.
36  */
37 #if 0
38 #define BTOR_LOG_MEM(FMT, ARGS...)   \
39   do                                 \
40   {                                  \
41     fputs ("[btorlogmem] ", stdout); \
42     printf (FMT, ##ARGS);            \
43     fflush (stdout);                 \
44   } while (0)
45 #else
46 #define BTOR_LOG_MEM(...) \
47   do                      \
48   {                       \
49   } while (0)
50 #endif
51 
52 /*------------------------------------------------------------------------*/
53 
54 BtorMemMgr *
btor_mem_mgr_new(void)55 btor_mem_mgr_new (void)
56 {
57   BtorMemMgr *mm = (BtorMemMgr *) malloc (sizeof (BtorMemMgr));
58   BTOR_ABORT (!mm, "out of memory in 'btor_mem_mgr_new'");
59   mm->allocated        = 0;
60   mm->maxallocated     = 0;
61   mm->sat_allocated    = 0;
62   mm->sat_maxallocated = 0;
63   return mm;
64 }
65 
66 void *
btor_mem_malloc(BtorMemMgr * mm,size_t size)67 btor_mem_malloc (BtorMemMgr *mm, size_t size)
68 {
69   void *result;
70   if (!size) return 0;
71   assert (mm);
72   result = malloc (size);
73   BTOR_ABORT (!result, "out of memory in 'btor_mem_malloc'");
74   mm->allocated += size;
75   ADJUST ();
76   BTOR_LOG_MEM ("%p malloc %10ld\n", result, size);
77   return result;
78 }
79 
80 void *
btor_mem_sat_malloc(BtorMemMgr * mm,size_t size)81 btor_mem_sat_malloc (BtorMemMgr *mm, size_t size)
82 {
83   void *result;
84   if (!size) return 0;
85   assert (mm);
86   result = malloc (size);
87   BTOR_ABORT (!result, "out of memory in 'btor_mem_sat_malloc'");
88   mm->sat_allocated += size;
89   SAT_ADJUST ();
90   return result;
91 }
92 
93 void *
btor_mem_realloc(BtorMemMgr * mm,void * p,size_t old_size,size_t new_size)94 btor_mem_realloc (BtorMemMgr *mm, void *p, size_t old_size, size_t new_size)
95 {
96   void *result;
97   assert (mm);
98   assert (!p == !old_size);
99   assert (mm->allocated >= old_size);
100   BTOR_LOG_MEM ("%p free   %10ld (realloc)\n", p, old_size);
101   result = realloc (p, new_size);
102   BTOR_ABORT (!result, "out of memory in 'btor_mem_realloc'");
103   mm->allocated -= old_size;
104   mm->allocated += new_size;
105   ADJUST ();
106   BTOR_LOG_MEM ("%p malloc %10ld (realloc)\n", result, new_size);
107   return result;
108 }
109 
110 void *
btor_mem_sat_realloc(BtorMemMgr * mm,void * p,size_t old_size,size_t new_size)111 btor_mem_sat_realloc (BtorMemMgr *mm, void *p, size_t old_size, size_t new_size)
112 {
113   void *result;
114   assert (mm);
115   assert (!p == !old_size);
116   assert (mm->sat_allocated >= old_size);
117   result = realloc (p, new_size);
118   BTOR_ABORT (!result, "out of memory in 'btor_mem_sat_realloc'");
119   mm->sat_allocated -= old_size;
120   mm->sat_allocated += new_size;
121   SAT_ADJUST ();
122   return result;
123 }
124 
125 void *
btor_mem_calloc(BtorMemMgr * mm,size_t nobj,size_t size)126 btor_mem_calloc (BtorMemMgr *mm, size_t nobj, size_t size)
127 {
128   size_t bytes = nobj * size;
129   void *result;
130   assert (mm);
131   result = calloc (nobj, size);
132   BTOR_ABORT (!result, "out of memory in 'btor_mem_calloc'");
133   mm->allocated += bytes;
134   ADJUST ();
135   BTOR_LOG_MEM ("%p malloc %10ld (calloc)\n", result, bytes);
136   return result;
137 }
138 
139 void
btor_mem_free(BtorMemMgr * mm,void * p,size_t freed)140 btor_mem_free (BtorMemMgr *mm, void *p, size_t freed)
141 {
142   assert (mm);
143   assert (!p == !freed);
144   assert (mm->allocated >= freed);
145   mm->allocated -= freed;
146   BTOR_LOG_MEM ("%p free   %10ld\n", p, freed);
147   free (p);
148 }
149 
150 void
btor_mem_sat_free(BtorMemMgr * mm,void * p,size_t freed)151 btor_mem_sat_free (BtorMemMgr *mm, void *p, size_t freed)
152 {
153   assert (mm);
154   if (p) mm->sat_allocated -= freed;
155   free (p);
156 }
157 
158 char *
btor_mem_strdup(BtorMemMgr * mm,const char * str)159 btor_mem_strdup (BtorMemMgr *mm, const char *str)
160 {
161   char *res;
162 
163   if (str)
164   {
165     res = btor_mem_malloc (mm, strlen (str) + 1);
166     strcpy (res, str);
167   }
168   else
169     res = 0;
170 
171   return res;
172 }
173 
174 void
btor_mem_freestr(BtorMemMgr * mm,char * str)175 btor_mem_freestr (BtorMemMgr *mm, char *str)
176 {
177   if (str) btor_mem_free (mm, str, strlen (str) + 1);
178 }
179 
180 void
btor_mem_mgr_delete(BtorMemMgr * mm)181 btor_mem_mgr_delete (BtorMemMgr *mm)
182 {
183   assert (mm);
184   assert (getenv ("BTORLEAK") || getenv ("BTORLEAKMEM") || !mm->allocated);
185   free (mm);
186 }
187 
188 size_t
btor_mem_parse_error_msg_length(const char * name,const char * fmt,va_list ap)189 btor_mem_parse_error_msg_length (const char *name, const char *fmt, va_list ap)
190 {
191   /* Additional characters for:
192 
193   "<name>:<lineno>:[<columno>:] "
194 
195   */
196   size_t bytes = strlen (name) + 25;
197   const char *p;
198 
199   for (p = fmt; *p; p++)
200   {
201     if (*p == '%')
202     {
203       p++;
204       assert (*p);
205       if (*p == 'c')
206       {
207         (void) va_arg (ap, int32_t);
208         bytes += 1;
209       }
210       else if (*p == 'd' || *p == 'u')
211       {
212         (void) va_arg (ap, uint32_t);
213         bytes += 12;
214       }
215       else
216       {
217         assert (*p == 's');
218         bytes += strlen (va_arg (ap, const char *));
219       }
220     }
221     else
222       bytes++;
223   }
224 
225   return bytes;
226 }
227 
228 char *
btor_mem_parse_error_msg(BtorMemMgr * mem,const char * name,int32_t lineno,int32_t columno,const char * fmt,va_list ap,size_t bytes)229 btor_mem_parse_error_msg (BtorMemMgr *mem,
230                           const char *name,
231                           int32_t lineno,
232                           int32_t columno,
233                           const char *fmt,
234                           va_list ap,
235                           size_t bytes)
236 {
237   char *res;
238   char *tmp;
239 
240   tmp = btor_mem_malloc (mem, bytes);
241   if (columno > 0)
242     sprintf (tmp, "%s:%d:%d: ", name, lineno, columno);
243   else
244     sprintf (tmp, "%s:%d: ", name, lineno);
245   assert (strlen (tmp) + 1 < bytes);
246   vsprintf (tmp + strlen (tmp), fmt, ap);
247   res = btor_mem_strdup (mem, tmp);
248   btor_mem_free (mem, tmp, bytes);
249 
250   return res;
251 }
252