• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nasa / trick / 25870723371

14 May 2026 04:03PM UTC coverage: 56.928% (+0.2%) from 56.774%
25870723371

Pull #2117

github

web-flow
Merge 694a6c711 into af8c162b8
Pull Request #2117: Completed std::wstring support.

24 of 43 new or added lines in 6 files covered. (55.81%)

199 existing lines in 2 files now uncovered.

12974 of 22790 relevant lines covered (56.93%)

298441.05 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

67.29
/trick_source/sim_services/MemoryManager/MemoryManager_declare_var.cpp
1
#include <stdlib.h>
2
#include <iostream>
3

4
#include <sstream>
5
#include <dlfcn.h>
6
#include <string.h>
7
#include "trick/MemoryManager.hh"
8
#include "trick/ADefParseContext.hh"
9

10
/**
11
 @page examples_declare_var Examples of declare_var
12

13
 Allocation of an anonymous singleton of type double:
14
 \code double *D = (double*)trick_MM->declare_var("double"); \endcode
15

16
 Allocation of an anonymous array of 3 doubles:
17
 \code double *D = (double*)trick_MM->declare_var("double[3]"); \endcode
18

19
 Allocation of an anonymous array of 3 pointers to double:
20
 \code double **D = (double**)trick_MM->declare_var("double*[3]"); \endcode
21

22
 Allocation of an anonymous 2 dimensional array of doubles:
23
 \code double (*A)[3][4] = (double(*)[3][4])trick_MM->declare_var("double[3][4]"); \endcode
24

25
 Allocation of a named singleton of type double:
26
 \code double *D = (double*)trick_MM->declare_var("double mydbl"); \endcode
27

28
 Allocation of a named array of 3 Pointers to double:
29
 \code double **D = (double**)trick_MM->declare_var("double* mydbl[3]"); \endcode
30

31
 Allocation of a named singleton of user-defined type "BAR":
32
 \code BAR *D = (BAR*)trick_MM->declare_var("BAR mydbl"); \endcode
33

34
 Allocation of a named 2 dimensional array of user-defined type "BAR" in namespace "FOO":
35
 \code FOO::BAR (*A)[3][4] = (FOO::BAR(*)[3][4])trick_MM->declare_var("FOO::BAR my_array[3][4]"); \endcode
36
 */
37

38
// PUBLIC MEMBER FUNCTION: void* Trick::MemoryManager::declare_var(TRICK_TYPE type,std::string user_type_name, int n_stars, std::string var_name, int n_cdims, int *cdims);
39
void* Trick::MemoryManager::declare_var( TRICK_TYPE type,
6,884✔
40
                                        std::string user_type_name,
41
                                        int n_stars,
42
                                        std::string var_name,
43
                                        int n_cdims,
44
                                        int *cdims) {
45
    int size;
46
    char* allocation_name;
47
    int n_elems;
48
    Language language;
49
    TRICK_ALLOC_TYPE allocation_type;
50
    void* address;
51
    ATTRIBUTES* sub_attr;
52
    ALLOC_INFO *new_alloc;
53
    VARIABLE_MAP::iterator variable_pos;
6,884✔
54

55
    if (debug_level > 1) {
6,884✔
56
        std::cout << __FUNCTION__ << ": Parameters: " << std::endl;
×
57
        std::cout << "           type = " << type << std::endl;
×
58
        std::cout << "           user_type_name = " << user_type_name << std::endl;
×
59
        std::cout << "           n_stars = " << n_stars << std::endl;
×
60
        std::cout << "           var_name = " << var_name << std::endl;
×
61
        std::cout << "           n_cdims = " << n_cdims << std::endl;
×
62
    }
63

64
    /** @par Design Details:
65
     This function is implemented using the following algorithm:
66
     */
67

68
    /** @li If this is a named allocation then determine whether the given variable name is already in use. */
69
    if (var_name != "") {
6,884✔
70
        pthread_mutex_lock(&mm_mutex);
5,249✔
71
        variable_pos = variable_map.find( var_name);
5,249✔
72
        if (variable_pos != variable_map.end()) {
5,249✔
73
            std::stringstream message;
×
74
            message << "Variable \""<< var_name <<"\" already declared.\n";
×
75
            emitError(message.str());
×
76
            pthread_mutex_unlock(&mm_mutex);
×
77
            return ((void*)NULL);
×
78
        }
79
        pthread_mutex_unlock(&mm_mutex);
5,249✔
80
        allocation_name = strdup( var_name.c_str());
5,249✔
81
    } else {
82
        allocation_name = NULL;
1,635✔
83
    }
84

85
    /** @li Calculate the number of elements to be allocated. The number of elements is
86
            the product of the sizes of the constrained dimensions. */
87
    n_elems = 1;
6,884✔
88
    for (int ii = 0; ii < n_cdims ; ii++ ) {
13,089✔
89
        n_elems = n_elems * cdims[ii];
6,205✔
90
    }
91
    if (n_elems == 0) {
6,884✔
92
        std::stringstream message;
×
93
        message << "In the following declaration, ";
×
94
        message << "one or more of the constrained dimensions is zero." ;
×
95
        message << std::endl;
×
96

97
        // Print declaration.
98
        message << make_decl_string( type, user_type_name, n_stars, var_name, n_cdims, cdims);
×
99
        emitError(message.str()) ;
×
100
        return ((void*)NULL);
×
101
    }
102

103
    /** @li From the TRICK_TYPE, user_type_name and the number of pointers (asterisks),
104
            determine the size and the attributes of an element. */
105
    if ( get_type_attributes(type, user_type_name, n_stars, sub_attr, size) != 0) {
6,884✔
106
        std::stringstream message;
×
107
        message << "get_type_attributes failed for type: ";
×
108
        message << trickTypeCharString(type, user_type_name.c_str());
×
109
        message << std::endl;
×
110
        emitError(message.str()) ;
×
111

112
        return ((void*)NULL);
×
113
    }
114

115
    /** @li Allocate memory for the variable. */
116
    if ( (type == TRICK_STRUCTURED) &&
6,884✔
117
         (sub_attr->language == Language_CPP) &&
884✔
118
         (n_stars == 0 ) ) {
119

120
        if ((address = io_src_allocate_class( user_type_name.c_str(), n_elems)) == NULL) {
700✔
121
            std::stringstream message;
×
122
            message << "io_src_allocate_class (";
×
123
            message << user_type_name << "," << n_elems ;
×
124
            message << ") failed to allocate any memory.";
×
125
            emitError(message.str()) ;
×
126

127
            return ((void*)NULL);
×
128
        }
129
        language = Language_CPP;
700✔
130
        /* io_src_allocate_class allocates objects using calloc (only).  */
131
        allocation_type = TRICK_ALLOC_MALLOC;
700✔
132

133
    } else if ((type == TRICK_STRING) && (n_stars == 0 ) ) {
6,184✔
134

135
        std::string *s = (std::string*)calloc(n_elems, sizeof(std::string));
3,715✔
136
        for (int ii=0 ; ii<n_elems ; ii++) {
8,107✔
137
            new( &s[ii]) std::string();
4,392✔
138
        }
139
        address = s;
3,715✔
140

141
        if (address == NULL) {
3,715✔
NEW
142
            return ((void*)NULL);
×
143
        }
144
        language = Language_CPP;
3,715✔
145
    } else if ((type == TRICK_WSTRING) && (n_stars == 0 ) ) {
2,469✔
146

147
        std::wstring *s = (std::wstring*)calloc(n_elems, sizeof(std::wstring));
1✔
148
        for (int ii=0 ; ii<n_elems ; ii++) {
3✔
149
            new( &s[ii]) std::wstring();
2✔
150
        }
151
        address = s;
1✔
152

153
        if (address == NULL) {
1✔
154
            return ((void*)NULL);
×
155
        }
156
        language = Language_CPP;
1✔
157
    } else {
158
        if ( (address = calloc( (size_t)n_elems, (size_t)size ) ) == NULL) {
2,468✔
159
            emitError("Out of memory.") ;
×
160
            return ((void*)NULL);
×
161
        }
162
        language = Language_C;
2,468✔
163
    }
164

165
    /** @li Allocate and populate an ALLOC_INFO record for the allocation. */
166
    if ((new_alloc = (ALLOC_INFO*)calloc(1, sizeof(ALLOC_INFO))) != NULL) {
6,884✔
167

168
        new_alloc->start = address;
6,884✔
169
        new_alloc->end = ( (char*)new_alloc->start) + (n_elems * size) - 1;
6,884✔
170
        new_alloc->name = allocation_name;
6,884✔
171
        new_alloc->stcl = TRICK_LOCAL;
6,884✔
172
        new_alloc->size = size;
6,884✔
173
        new_alloc->language = language;
6,884✔
174
        new_alloc->type = type;
6,884✔
175
        new_alloc->alloc_type = allocation_type;
6,884✔
176

177
        if ((type == TRICK_STRUCTURED) || (type == TRICK_ENUMERATED)) {
6,884✔
178
            new_alloc->user_type_name = strdup( user_type_name.c_str());
920✔
179
        } else {
180
            new_alloc->user_type_name = NULL ;
5,964✔
181
        }
182

183
        new_alloc->attr = sub_attr;
6,884✔
184
        new_alloc->num = n_elems;
6,884✔
185

186
        new_alloc->num_index = 0;
6,884✔
187
        for (int ii = 0; ii < n_cdims ; ii++ ) {
13,089✔
188
            new_alloc->index[new_alloc->num_index] = cdims[ii];
6,205✔
189
            new_alloc->num_index ++ ;
6,205✔
190
        }
191
        for (int ii = 0 ; ii < n_stars ; ii++) {
7,307✔
192
            new_alloc->index[new_alloc->num_index] = 0;
423✔
193
            new_alloc->num_index ++ ;
423✔
194
        }
195

196
        new_alloc->id = alloc_info_map_counter++ ;
6,884✔
197

198
        /** @li Insert the <address, ALLOC_INFO> key-value pair into the alloc_info_map.*/
199
        pthread_mutex_lock(&mm_mutex);
6,884✔
200
        alloc_info_map[address] = new_alloc;
6,884✔
201

202
        /** @li If this is a named allocation: then insert the <variable-name, ALLOC_INFO>
203
            key-value pair into the variable map.*/
204
        if (new_alloc->name) {
6,884✔
205
            variable_map[new_alloc->name] = new_alloc;
5,249✔
206
        }
207
        pthread_mutex_unlock(&mm_mutex);
6,884✔
208
    } else {
209
        emitError("Out of memory.\n") ;
×
210
        return ((void*)NULL);
×
211
    }
212

213
    /** @li If debug is enabled, show what happened.*/
214
    if (debug_level) {
6,884✔
215
        int i;
216
        std::cout << std::endl;
×
217
        std::cout << "Allocation: " << new_alloc->num << " element(s) of type(" ;
×
218
        std::cout << trickTypeCharString(type, user_type_name.c_str()) ;
×
219
        for (i=0;i<n_stars;i++) std::cout << "*";
×
220
        std::cout << "), size(" << size << ") @ addr(" << address << ")." ;
×
221
        std::cout << std::endl << std::endl;
×
222
        std::cout.flush();
×
223
    }
224

225
    /** @li Return the address of the allocation. */
226
    return (address);
6,884✔
227
}
228

229
// PUBLIC MEMBER FUNCTION: void* Trick::MemoryManager::declare_var( const char *alloc_definition);
230
void* Trick::MemoryManager::declare_var( const char *alloc_definition) {
3,909✔
231

232
    void* address = NULL;
3,909✔
233

234
    Trick::ADefParseContext* context = NULL;
3,909✔
235
    std::stringstream alloc_decl_sstream;
3,909✔
236

237
    /** @par Design Details:
238
     This function is implemented using the following algorithm:
239
     */
240

241
    alloc_decl_sstream << alloc_definition;
3,909✔
242

243
    /** @li Create a parse context. */
244
    context = new Trick::ADefParseContext( &alloc_decl_sstream);
3,909✔
245

246
    /** @li Call ADEF_parse to parse the allocation definition. */
247
    if (context != NULL) {
3,909✔
248
        if ( ADEF_parse( context) == 0) {
3,909✔
249

250
            /** @li Call the general form of declare_var to perform the allocation. */
251
            address = declare_var( context->type,
3,907✔
252
                                  context->user_type_name,
3,907✔
253
                                  context->n_stars,
254
                                  context->var_name,
3,907✔
255
                                  context->n_cdims,
256
                                  context->cdims);
3,907✔
257

258
            /** @li Delete the parse context. */
259
            delete( context);
3,907✔
260
        } else {
261
            std::stringstream message;
2✔
262
            message << "Invalid declaration (failed to parse): \"" << alloc_definition << "\".";
2✔
263
            emitError(message.str());
2✔
264
        }
265
    }
266
    /** @li Return the address of the allocation. */
267
    return ( address);
7,818✔
268
}
269

270
// PUBLIC MEMBER FUNCTION: void* Trick::MemoryManager::declare_var( const char *element_definition, int n_elems);
271

272
void* Trick::MemoryManager::declare_var( const char *element_definition, int n_elems) {
834✔
273

274
    void* address = NULL;
834✔
275
    int cdims[8];
276
    int n_cdims;
277

278
    Trick::ADefParseContext* context = NULL;
834✔
279
    std::stringstream alloc_decl_sstream;
834✔
280

281
    /** We know that our array will be at least one dimensional and that dimension contains n_elems elements. */
282
    cdims[0] = n_elems;
834✔
283
    n_cdims = 1;
834✔
284

285
    alloc_decl_sstream << element_definition;
834✔
286

287
    /** @li Create a parse context. */
288
    context = new Trick::ADefParseContext( &alloc_decl_sstream);
834✔
289

290
    if (context != NULL) {
834✔
291

292
    /** @li Parse the allocation definition and ensure that the dimension is at least one less than the maximum of 8. */
293
        if (( ADEF_parse( context) == 0) && (context->n_cdims < 8) ){
834✔
294

295
            /** @li Add the dimensions of the element definition. */
296
            for (int ii=0 ; ii < context->n_cdims ; ii++) {
834✔
297
                cdims[ii+1] = context->cdims[ii];
×
298
                n_cdims ++;
×
299
            }
300

301
            /** @li Call the general form of declare_var to perform the allocation. */
302
            address = declare_var( context->type,
834✔
303
                                   context->user_type_name,
834✔
304
                                   context->n_stars,
305
                                   context->var_name,
834✔
306
                                   n_cdims,
307
                                   cdims);
308

309
            /** @li Delete the parse context. */
310
            delete( context);
834✔
311
        } else {
312
            std::stringstream message;
×
313
            message << "declare_var( \"" << element_definition << "\"," << n_elems <<").";
×
314
            emitError(message.str());
×
315
        }
316
    }
317
    /** @li Return the address of the allocation. */
318
    return ( address);
1,668✔
319
}
320

321
// PUBLIC MEMBER FUNCTION: void* Trick::MemoryManager::declare_operatornew_var(std::string user_type_name, unsigned int alloc_size , unsigned int element_size, std::string alloc_name );
322

323
void* Trick::MemoryManager::declare_operatornew_var( std::string user_type_name, unsigned int alloc_size , unsigned int element_size , std::string alloc_name ) {
2✔
324
    TRICK_TYPE type = TRICK_STRUCTURED ;
2✔
325
    int size_ref = 1 ;
2✔
326
    void* address;
327
    int aligned;
328
    ATTRIBUTES* sub_attr;
329
    ALLOC_INFO *new_alloc;
330

331
    if (debug_level > 1) {
2✔
332
        std::cout << __FUNCTION__ << ": Parameters: " << std::endl;
×
333
        std::cout << "           user_type_name = " << user_type_name << std::endl;
×
334
        std::cout << "               alloc_size = " << alloc_size << std::endl;
×
335
        std::cout << "             element_size = " << element_size << std::endl;
×
336
    }
337

338
    /** @li From the TRICK_TYPE, user_type_name and the number of pointers (asterisks),
339
            determine the size and the attributes of an element. */
340
    if ( get_type_attributes(type, user_type_name, 0, sub_attr, size_ref ) != 0) {
2✔
341
        std::stringstream message;
×
342
        message << "get_type_attributes failed for type: " << TRICK_STRUCTURED
×
343
                << " " << user_type_name.c_str() << ".";
×
344
        emitError(message.str());
×
345
        return ((void*)NULL);
×
346
    }
347

348
    if ( (address = calloc( 1, alloc_size ) ) == NULL) {
2✔
349
        emitError("Out of memory.") ;
×
350
        return ((void*)NULL);
×
351
    }
352

353
    aligned = alloc_size % element_size ;
2✔
354

355
    /** @li Allocate and populate an ALLOC_INFO record for the allocation. */
356
    if ((new_alloc = (ALLOC_INFO*)calloc(1, sizeof(ALLOC_INFO))) != NULL) {
2✔
357

358
        new_alloc->start = (char *)address + aligned ;
2✔
359
        new_alloc->end = ( (char*)new_alloc->start) + alloc_size - 1 - aligned ;
2✔
360
        if (alloc_name != "") {
2✔
361
            new_alloc->name = strdup(alloc_name.c_str());
1✔
362
        } else {
363
            new_alloc->name = NULL;
1✔
364
        }
365
        new_alloc->stcl = TRICK_LOCAL;
2✔
366
        new_alloc->size = element_size ;
2✔
367
        new_alloc->sentinel_bytes = aligned ;
2✔
368
        new_alloc->language = Language_CPP ;
2✔
369
        new_alloc->type = TRICK_STRUCTURED ;
2✔
370

371
        new_alloc->user_type_name = strdup( user_type_name.c_str());
2✔
372

373
        new_alloc->attr = sub_attr;
2✔
374
        new_alloc->num = alloc_size / element_size ;
2✔
375

376
        new_alloc->num_index = 1;
2✔
377
        new_alloc->index[0] = new_alloc->num ;
2✔
378

379
        new_alloc->id = alloc_info_map_counter++ ;
2✔
380

381
        /** @li Insert the <address, ALLOC_INFO> key-value pair into the alloc_info_map.*/
382
        pthread_mutex_lock(&mm_mutex);
2✔
383
        alloc_info_map[address] = new_alloc;
2✔
384
        /** @li If this is a named allocation: then insert the <variable-name, ALLOC_INFO>
385
            key-value pair into the variable map.*/
386
        if (new_alloc->name) {
2✔
387
            variable_map[new_alloc->name] = new_alloc;
1✔
388
        }
389
        pthread_mutex_unlock(&mm_mutex);
2✔
390
    } else {
391
        emitError("Out of memory.") ;
×
392
        return ((void*)NULL);
×
393
    }
394

395
    /** @li If debug is enabled, show what happened.*/
396
    if (debug_level ) {
2✔
397
        std::cout << std::endl;
×
398
        std::cout << "Allocation: " << new_alloc->num << " element(s) of type(" ;
×
399
        std::cout << user_type_name ;
×
400
        std::cout << "), size(" << new_alloc->size << ") @ addr(" << address << ") sentinel_bytes = " << new_alloc->sentinel_bytes ;
×
401
        std::cout << std::endl << std::endl;
×
402
        std::cout.flush();
×
403
    }
404

405
    /** @li Return the address of the allocation. */
406
    return (address);
2✔
407
}
408

409
// PUBLIC MEMBER FUNCTION: size_t Trick::MemoryManager::sizeof_type( const char* var_definition);
410

411
size_t Trick::MemoryManager::sizeof_type( const char* var_definition) {
21✔
412

413
    int size = 0 ;
21✔
414
    int n_elems = 0 ;
21✔
415
    ATTRIBUTES* sub_attr;
416

417
    Trick::ADefParseContext* context = NULL;
21✔
418
    std::stringstream alloc_decl_sstream;
21✔
419

420
    alloc_decl_sstream << var_definition;
21✔
421
    context = new Trick::ADefParseContext( &alloc_decl_sstream);
21✔
422
    if (context != NULL) {
21✔
423
        if ( ADEF_parse( context) == 0) {
21✔
424

425
            get_type_attributes(context->type, context->user_type_name, context->n_stars, sub_attr, size);
21✔
426

427
            n_elems = 1;
21✔
428
            for (int ii=0; ii<context->n_cdims ; ii++) {
31✔
429
                n_elems *= context->cdims[ii];
10✔
430
            }
431
        } else {
432
            std::stringstream message;
×
433
            message << "Invalid variable definition \"" << var_definition << "\" in sizeof_type.";
×
434
            emitError(message.str());
×
435
        }
436
        delete( context);
21✔
437
    }
438

439
    return (size_t)(n_elems * size);
42✔
440
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc