1 /*******************************************************************************
2 *
3 * McStas, neutron ray-tracing package
4 *         Copyright (C) 1997-2009, All rights reserved
5 *         Risoe National Laboratory, Roskilde, Denmark
6 *         Institut Laue Langevin, Grenoble, France
7 *
8 * Kernel: memory.c
9 *
10 * %Identification
11 * Written by: K.N.
12 * Date: Jul  1, 1997
13 * Origin: Risoe
14 * Release: McStas CVS_090504
15 * Version: $Revision$
16 *
17 * Memory management functions.
18 *
19 *       $Id$
20 *
21 *******************************************************************************/
22 
23 #include <string.h>
24 #include <stdlib.h>
25 #include <stdarg.h>
26 #include <ctype.h>
27 #include <stdio.h>
28 
29 #include "mccode.h"
30 
31 
32 /*******************************************************************************
33 * Allocate memory. This function never returns NULL; instead, the
34 * program is aborted if insufficient memory is available.
35 *******************************************************************************/
36 void *
mem(size_t size)37 mem(size_t size)
38 {
39   void *p = calloc(1, size);    /* Allocate and clear memory. */
40   if(p == NULL)
41     fatal_error("memory exhausted during allocation of size %ld.", (long)size);
42   return p;
43 }
44 
45 /*******************************************************************************
46 * Free memory allocated with mem().
47 *******************************************************************************/
memfree(void * p)48 void memfree(void *p)
49 {
50   if(p == NULL)
51     debug(("memfree(): freeing NULL memory.\n"));
52   else
53     free(p);
54 }
55 
56 /*******************************************************************************
57 * Allocate a new copy of a string.
58 *******************************************************************************/
59 char *
str_dup(char * string)60 str_dup(char *string)
61 {
62   char *s;
63 
64   s = mem(strlen(string) + 1);
65   strcpy(s, string);
66   return s;
67 }
68 
69 
70 /*******************************************************************************
71 * Allocate a new copy of initial N chars in a string.
72 *******************************************************************************/
73 char *
str_dup_n(char * string,int n)74 str_dup_n(char *string, int n)
75 {
76   char *s;
77 
78   s = mem(n + 1);
79   strncpy(s, string, n);
80   s[n] = '\0';
81   return s;
82 }
83 
84 
85 /*******************************************************************************
86 * Allocate a new string to hold the concatenation of given strings. Arguments
87 * are the strings to concatenate, terminated by NULL.
88 *******************************************************************************/
89 char *
str_cat(char * first,...)90 str_cat(char *first, ...)
91 {
92   char *s;
93   va_list ap;
94   int size;
95   char *arg;
96 
97   size = 1;                     /* Count final '\0'. */
98   va_start(ap, first);
99   for(arg = first; arg != NULL; arg = va_arg(ap, char *))
100     size += strlen(arg);        /* Calculate string size. */
101   va_end(ap);
102   s = mem(size);
103   size = 0;
104   va_start(ap, first);
105   for(arg = first; arg != NULL; arg = va_arg(ap, char *))
106   {
107     strcpy(&(s[size]), arg);
108     size += strlen(arg);
109   }
110   va_end(ap);
111   return s;
112 }
113 
114 /*******************************************************************************
115 * Allocate a new string holding the result of quoting the input string. The
116 * result is suitable for inclusion in C source code.
117 *******************************************************************************/
118 char *
str_quote(char * string)119 str_quote(char *string)
120 {
121   char *badchars = "\\\"\r\n\t";
122   char *quotechars = "\\\"rnt";
123   char *q=NULL, *res=NULL, *ptr;
124   int len, pass;
125   int c;
126   char new[5];
127 
128   /* Loop over the string twice, first counting chars and afterwards copying
129      them into an allocated buffer. */
130   for(pass = 0; pass < 2; pass++)
131   {
132     char *p = string;
133 
134     if(pass == 0)
135       len = 0;                  /* Prepare to compute length */
136     else
137       q = res = mem(len + 1);   /* Allocate buffer */
138     /* Notice the cast to unsigned char; without it, the isprint(c) below will
139        fail for characters with negative plain char values. */
140     while((c = (unsigned char)(*p++)))
141     {
142       ptr = strchr(badchars, c);
143       if(ptr != NULL)
144         sprintf(new, "\\%c", quotechars[ptr - badchars]);
145       else if(isprint(c))
146         sprintf(new, "%c", c);
147       else
148         sprintf(new, "\\%03o", c);
149       if(pass == 0)
150         len += strlen(new);     /* Count in length */
151       else
152         for(ptr = new; (*q = *ptr) != 0; ptr++)
153           q++;                  /* Copy over chars */
154     }
155   }
156   return res;
157 }
158 
159 
160 /*******************************************************************************
161 * Free memory for a string.
162 *******************************************************************************/
163 void
str_free(char * string)164 str_free(char *string)
165 {
166   memfree(string);
167 }
168 
169 #ifndef MCFORMAT
170 
171 struct Pool_header
172   {
173     List list;
174   };
175 
176 /*******************************************************************************
177 * Create a pool in which to allocate memory that may be easily freed all at a
178 * time by freeing the pool.
179 *******************************************************************************/
180 Pool
pool_create(void)181 pool_create(void)
182 {
183   Pool p;
184 
185   palloc(p);
186   p->list = list_create();
187   return p;
188 }
189 
190 /*******************************************************************************
191 * Deallocate a pool as well as all memory allocated within it.
192 *******************************************************************************/
193 void
pool_free(Pool p)194 pool_free(Pool p)
195 {
196   List_handle liter;
197   void *mem;
198 
199   liter = list_iterate(p->list);
200   while(mem = list_next(liter))
201   {
202     memfree(mem);
203   }
204   list_iterate_end(liter);
205   memfree(p);
206 }
207 
208 
209 /*******************************************************************************
210 * Allocate memory in a pool.
211 *******************************************************************************/
212 void *
pool_mem(Pool p,size_t size)213 pool_mem(Pool p, size_t size)
214 {
215   void *m = mem(size);
216   list_add(p->list, m);
217   return m;
218 }
219 
220 #endif /* MCSTAS_H */
221